成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

實現TypeScript中的互斥類型

開發 前端
在TypeScript中它有一個特殊的類型never,它是所有類型的子類型,無法再進行細分,也就意味著除了其本身沒有類型可以再分配給它。

前置知識

在實現之前,我們需要先來了解幾個基礎的知識。

對象中多屬性同類型的定義

有一個對象它包含5個可選屬性a、b、c、d、e,他們的類型都為string,大多數人的定義方式應該如下所示:

type obj = {
a?:string;
b?:string;
c?:string;
d?:string;
e?:string;
}

那么,有沒有更好的方式呢??,答案是有的,請看我的表演:

type obj = { [P in "a" | "b" | "c" | "d" | "e"]?: string };

never類型

在TypeScript中它有一個特殊的類型never,它是所有類型的子類型,無法再進行細分,也就意味著除了其本身沒有類型可以再分配給它。

我們舉個例子來解釋下上述話語,如下所示:

  • 我們定義了一個變量amazing,給其賦予了never類型。
  • 我們分別給它賦了不同類型的值,全部編譯失敗,因為它無法再進行細分了。
let amazing: never;
amazing = 12;// 報錯:amazing是never類型不能分配給number類型
amazing = true;// 報錯:amazing是never類型不能分配給boolean類型
amazing = "真神奇";// 報錯:amazing是never類型不能分配給string類型
amazing = {};// 報錯:amazing是never類型不能分配給{}類型
amazing = [];// 報錯:amazing是never類型不能分配給[]類型

剔除聯合類型中的屬性

有一組聯合類型"a" | "b" | "c" | "d",我們想剔除屬性b和c,在TS中提供了一個名為Exclude的函數,它可以用來做這件事,接受兩個參數:

  • UnionType 聯合類型
  • ExcludedMembers 需要進行剔除的屬性

使用方法如下所示:

type P = Exclude<"a" | "b" | "c" | "d", "b" | "c"> // "a" | "d"

將對象中的所有屬性轉為聯合類型

有一個對象它包含2個可選屬性name、title,我們想把它轉為聯合類型name | title ,在TS中提供了一個名為keyof的函數,他可以用來處理這個問題,使用方法如下所示:

type A =  { [P in "name" | "title"]?: string };

type UnionType = keyof A; // "name" | "string"

實現互斥類型

有了前置知識作為鋪墊,接下來我們就可以將其利用起來,定義一個互斥類型出來,解決文章開頭所講述的問題。

接下來,我們來梳理下實現思路:

  • 實現一個排除類型,用于從A對象類型中剔除B對象類型中的屬性,并將排除后的屬性類型設為never,得到一個新對象類型。
  • 基于排除類型實現互斥類型,將A、B對象類型代入排除類型中,彼此將其排除,用或運算符將二者結果連接。

聰明的開發者可能已經猜到原理了,沒錯,就是部分屬性設為never。??

實現代碼

接下來,我們來看下代碼的實現,如下所示:

// 定義排除類型:將U從T中剔除, keyof 會取出T與U的所有鍵, 限定P的取值范圍為T中的所有鍵, 并將其類型設為never
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };

// 定義互斥類型,T或U只有一個能出現(互相剔除時,被剔除方必須存在)
type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);

注意:為了類型的可復用性,我們使用了泛型,對此不熟悉的開發者請移步:TypeScript中文網——泛型[1]

測試用例

我們將文章開頭所說的問題代入上述實現代碼中,看一下它能否將其解決??,如下所示:

// A類型
type A = {
name: string;
};

// B類型
type B = {
title: string;
};

// A和B兩種類型只有一個能出現
type AOrB = XOR<A, B>;

// 傳值測試
const AOrB1: AOrB = { name: "姓名" }; // 編譯通過
const AOrB2: AOrB = { title: "標題" }; // 編譯通過
const AOrB3: AOrB = { title: "標題", name: "姓名" }; // 報錯: Type '{ title: string; name: string; }' is not assignable to type 'AOrB'.
const AOrB4: AOrB = { name: "姓名", otherKey: "" }; // 報錯:Type '{ name: string; otherKey: string; }' is not assignable to type 'AOrB'.

當兩個屬性同時出現時,編輯器直接就拋出了類型錯誤(我們把排除后的所有屬性的類型設為了never,因此當你給其賦任何值時它都會報類型錯誤),如下圖所示:

用例拆解

有一部分開發者可能對上述測試用例比較懵,把它們拆開都認識,因為前置知識里都講了,但是寫到一起就不認識了??,沒關系,那我就把它們都拆解出來吧,代碼如下所示:

type AOB = ({ name?: never } & {
title: string;
}) | ({ title?: never } & {
name: string;
});

// 傳值測試
const a: AOB = { name: "姓名" }; // 編譯通過
const b: AOB = { title: "標題" }; // 編譯通過
const c: AOB = { title: "標題", name: "姓名" }; // 報錯
const d: AOB = { title: "標題", otherKey: "" }; // 報錯
責任編輯:武曉燕 來源: 神奇的程序員
相關推薦

2021-07-27 06:06:34

TypeScript語言運算符

2024-05-11 10:19:31

TypeScript類型接口

2022-08-08 09:00:42

TypeScript映射類型

2022-05-04 09:02:41

TypeScript類型工具

2021-06-09 07:55:19

Typescript類型檢查

2022-09-14 15:24:57

typescript快排

2022-04-10 19:26:07

TypeScript類型語法

2020-12-18 11:35:22

TypeScript語言Java

2022-02-25 09:06:02

TypeScripnever工具

2021-06-05 21:30:24

typescriptOverride檢查

2021-08-18 07:56:05

Typescript類型本質

2022-02-09 08:11:50

架構

2024-08-12 08:50:17

2011-01-14 13:50:37

2021-06-03 08:03:13

網絡

2022-09-20 14:43:55

TypeScript類型體操

2025-01-20 00:13:19

TypeScript操作符數據類型

2024-06-24 08:10:00

C++互斥鎖

2020-09-15 08:35:57

TypeScript JavaScript類型

2022-08-10 09:03:35

TypeScript前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品69毛片高清亚洲 | 国产精品揄拍一区二区 | 日韩中文字幕免费在线观看 | 精品久久久久一区二区国产 | 日韩精品免费在线观看 | 亚洲欧美在线免费观看 | 超碰97免费 | 337p日本欧洲亚洲大胆鲁鲁 | 亚洲精品成人免费 | 欧美亚洲国产一区二区三区 | 成人小视频在线观看 | 亚洲一区二区电影网 | 久久午夜国产精品www忘忧草 | cao在线 | 国产精品亚洲成在人线 | 天天干天天爱天天 | 国产成人精品一区二区三区在线观看 | 免费黄色录像视频 | 久久久亚洲 | 欧美一级欧美一级在线播放 | 免费人成在线观看网站 | 精品国产一区二区三区四区在线 | 青娱乐av | 国产日韩av一区二区 | 成人激情视频在线播放 | 韩日av在线 | a在线免费观看视频 | 久久大全| av在线成人| 国产欧美一区二区三区在线看蜜臀 | 国产乱码精品一区二区三区五月婷 | 精品国产一区二区三区久久久蜜月 | xx性欧美肥妇精品久久久久久 | 凹凸日日摸日日碰夜夜 | 国产高清精品网站 | 日日日视频 | 视频在线亚洲 | www.亚洲一区二区 | 久草热视频| 久草新在线 | 亚洲日本一区二区 |