日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
用了TS條件類(lèi)型,同事直呼YYDS!

阿寶哥精心準(zhǔn)備的《輕松學(xué) TypeScript》 視頻教程已經(jīng)更新到第十期了,通過(guò)形象生動(dòng)的動(dòng)畫(huà),讓你輕松搞懂 TypeScript 的難點(diǎn)和核心知識(shí)點(diǎn)!

你用過(guò) Exclude、Extract、NonNullable、Parameters 和 ReturnType 這些工具類(lèi)型嗎?

type Exclude = T extends U ? never : T;
type Extract = T extends U ? T : never;
type NonNullable = T extends null | undefined ? never : T;
type Parameters any> = T extends (...args: infer P) => any ? P : never;
type ReturnType any> = T extends (...args: any) => infer R ? R : any;

你知道它們內(nèi)部是如何工作的嗎?如果你想徹底掌握它們且實(shí)現(xiàn)自己的工具類(lèi)型,那么本文千萬(wàn)不要錯(cuò)過(guò)。上面看到的那些內(nèi)置工具類(lèi)型,它們內(nèi)部使用了 TypeScript 2.8 版本引入的條件類(lèi)型(Conditional Types)。

該類(lèi)型的語(yǔ)法如下:

T extends U ? X : Y

其中 T、U、X 和 Y 這些都是類(lèi)型占位符。你可以這樣理解該語(yǔ)法,當(dāng)類(lèi)型 T 可以賦值給類(lèi)型 U 時(shí),那么返回類(lèi)型 X,否則返回類(lèi)型 Y。

看到這里你是不是也想到了 JavaScript 中的三元表達(dá)式。那么條件類(lèi)型有什么用呢?這里我們來(lái)舉個(gè)例子:

type IsString = T extends string ? true : false;
type I0 = IsString; // false
type I1 = IsString<"abc">; // true
type I2 = IsString; // boolean
type I3 = IsString; // never

在以上代碼中,我們定義了 IsString 工具類(lèi)型。使用該工具類(lèi)型,我們可以判斷傳給類(lèi)型參數(shù) T 的實(shí)際類(lèi)型是否為字符串類(lèi)型。除了判斷單一類(lèi)型之外,利用條件類(lèi)型和條件鏈,我們還可以同時(shí)判斷多種類(lèi)型。

下面我們來(lái)看一下如何實(shí)現(xiàn)該功能:

type TypeName =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends undefined ? "undefined" :
T extends Function ? "function" :
"object";
type T0 = TypeName; // "string"
type T1 = TypeName<"a">; // "string"
type T2 = TypeName; // "boolean"
type T3 = TypeName<() => void>; // "function"
type T4 = TypeName; // "object"

在以上代碼中,我們定義了一個(gè)新的 TypeName 工具類(lèi)型,在該工具類(lèi)型中,我們使用了條件鏈。為了便于大家理解條件鏈,我們以 JavaScript 三元表達(dá)式為例,來(lái)演示一下它的作用。

function example(…) {
return condition1 ? value1
: condition2 ? value2
: condition3 ? value3
: value4;
}
// 等價(jià)于
function example(…) {
if (condition1) { return value1; }
else if (condition2) { return value2; }
else if (condition3) { return value3; }
else { return value4; }
}

現(xiàn)在問(wèn)題來(lái)了,對(duì)于前面定義的 TypeName 工具類(lèi)型來(lái)說(shuō),如果傳入的類(lèi)型是聯(lián)合類(lèi)型的話,那么將返回什么結(jié)果?下面我們來(lái)驗(yàn)證一下:

type T10 = TypeName void)>;  // "string" | "function"
type T11 = TypeName; // "string" | "object" | "undefined"

為什么 T10 和 T11 類(lèi)型返回的是聯(lián)合類(lèi)型呢?這是因?yàn)?TypeName 屬于分布式條件類(lèi)型。在條件類(lèi)型中,如果被檢查的類(lèi)型是一個(gè) “裸” 類(lèi)型參數(shù),即沒(méi)有被數(shù)組、元組或 Promise 等包裝過(guò),則該條件類(lèi)型被稱(chēng)為分布式條件類(lèi)型。對(duì)于分布式條件類(lèi)型來(lái)說(shuō),當(dāng)傳入的被檢查類(lèi)型是聯(lián)合類(lèi)型的話,在運(yùn)算過(guò)程中會(huì)被分解成多個(gè)分支。

T extends U ? X : Y 
T => A | B | C
A | B | C extends U ? X : Y =>
(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)

為了便于大家理解,我們來(lái)舉個(gè)例子:

type Naked = T extends boolean ? "Y" : "N";
type WrappedTuple = [T] extends [boolean] ? "Y" : "N";
type WrappedArray = T[] extends boolean[] ? "Y" : "N";
type WrappedPromise = Promise extends Promise ? "Y" : "N";
type T0 = Naked; // "N" | "Y"
type T1 = WrappedTuple; // "N"
type T2 = WrappedArray; // "N"
type T3 = WrappedPromise; // "N"

由以上結(jié)果可知,如果條件類(lèi)型中的類(lèi)型參數(shù) T 被包裝過(guò),該條件類(lèi)型就不屬于分布式條件類(lèi)型,所以在運(yùn)算過(guò)程中就不會(huì)被分解成多個(gè)分支。

了解完條件類(lèi)型和分布式條件類(lèi)型的知識(shí)點(diǎn),我們來(lái)舉例演示一下 TypeScript 內(nèi)置工具類(lèi)型 Exclude 的執(zhí)行流程。

type Exclude = T extends U ? never : T;
type T4 = Exclude<"a" | "b" | "c", "a" | "b">
("a" extends "a" | "b" ? never : "a") // => never
| ("b" extends "a" | "b" ? never : "b") // => never
| ("c" extends "a" | "b" ? never : "c") // => "c"
never | never | "c" // => "c"

掌握了條件類(lèi)型之后,再結(jié)合往期文章中介紹的映射類(lèi)型,我們就可以實(shí)現(xiàn)一些有用的工具類(lèi)型。比如實(shí)現(xiàn) FunctionProperties 和 NonFunctionProperties 等工具類(lèi)型。

type FunctionPropertyNames = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type FunctionProperties = Pick>;
type NonFunctionPropertyNames = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type NonFunctionProperties = Pick>;
interface User {
id: number;
name: string;
age: number;
updateName(newName: string): void;
}
type T5 = FunctionPropertyNames; // "updateName"
type T6 = FunctionProperties; // { updateName: (newName: string) => void; }
type T7 = NonFunctionPropertyNames; // "id" | "name" | "age"
type T8 = NonFunctionProperties; // { id: number; name: string; age: number; }

在以上代碼中,利用上述的工具類(lèi)型,我們就可以輕松地提取 User 對(duì)象類(lèi)型中函數(shù)類(lèi)型和非函數(shù)類(lèi)型的屬性及相關(guān)的對(duì)象類(lèi)型。


文章題目:用了TS條件類(lèi)型,同事直呼YYDS!
網(wǎng)頁(yè)URL:http://www.5511xx.com/article/cdesgih.html