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

學會 TS infer,寫起泛型真香!

開發 前端
你知道如何獲取 T0 數組類型中元素的類型和 T1 函數類型中的返回值類型么?給你 3 秒鐘的時間思考一下。

你知道如何獲取 T0 數組類型中元素的類型和 T1 函數類型中的返回值類型么?給你 3 秒鐘的時間思考一下。

type T0 = string[];
type T1 = () => string;

要實現上述的功能,我們可以使用 TypeScript 提供的類型模式匹配技術 —— 條件類型 + infer。條件類型允許我們檢測兩種類型之間的關系,通過條件類型我們就可以判斷兩種類型是否相兼容。而 infer 用于聲明類型變量,以存儲在模式匹配過程中所捕獲的類型。

下面我們來看一下如何捕獲 T0 數組類型中元素的類型:

type UnpackedArray<T> = T extends (infer U)[] ? U : T
type U0 = UnpackedArray<T0> // string

在以上代碼中,T extends (infer U)[] ? U : T 是條件類型的語法,而 extends 子句中的 infer U 引入了一個新的類型變量 U,用于存儲被推斷的類型。

為了便于大家的理解,我們來演示一下 UnpackedArray 工具類型的執行流程。

type U0 = UnpackedArray<T0>

// T => T0: string[]
type UnpackedArray<string[]> = string[] extends (infer U)[] ? U : string[]
// string[] extends (infer U)[] 模式匹配成功
// U => string

需要注意的是,infer 只能在條件類型的 extends 子句中使用,同時 infer 聲明的類型變量只在條件類型的 true 分支中可用。

type Wrong1<T extends (infer U)[]> = T[0] // Error
type Wrong2<T> = (infer U)[] extends T ? U : T // Error
type Wrong3<T> = T extends (infer U)[] ? T : U // Error

了解完這些知識之后,我們來看一下如何獲取 T1 函數類型的返回值類型:

type UnpackedFn<T> = T extends (...args: any[]) => infer U ? U : T;

type U1 = UnpackedFn<T1>; // string

看完 UnpackedFn 工具類型的實現,是不是覺得挺簡單的。當遇到函數重載的場景,TypeScript 將使用最后一個調用簽名進行類型推斷:

declare function foo(x: string): number;
declare function foo(x: number): string;
declare function foo(x: string | number): string | number;

type UnpackedFn<T> = T extends (...args: any[]) => infer U ? U : T;
type U2 = UnpackedFn<typeof foo>; // string | number

如果你對 TypeScript 的條件類型還不了解的話,建議觀看 “用了 TS 條件類型,同事直呼 YYDS” 這篇文章。在該篇文章中,我們介紹了條件鏈,利用條件鏈我們可以實現功能更加強大的 Unpacked 工具類型。

type Unpacked<T> =
T extends (infer U)[] ? U :
T extends (...args: any[]) => infer U ? U :
T extends Promise<infer U> ? U :
T;

type T0 = Unpacked<string>; // string
type T1 = Unpacked<string[]>; // string
type T2 = Unpacked<() => string>; // string
type T3 = Unpacked<Promise<string>>; // string
type T4 = Unpacked<Promise<string>[]>; // Promise<string>
type T5 = Unpacked<Unpacked<Promise<string>[]>>; // string

在以上代碼中,Unpacked 工具類型利用了條件類型和條件鏈,輕松實現了推斷出數組類型中元素的類型、函數類型返回值的類型和 Promise 類型中返回值的類型的功能。

其實,利用條件類型和 infer,我們還可以推斷出對象類型中鍵的類型。接下來,我們來舉個具體的例子:

type User = {
id: number;
name: string;
}

type PropertyType<T> = T extends { id: infer U, name: infer R } ? [U, R] : T
type U3 = PropertyType<User> // [number, string]

在 PropertyType 工具類型中,我們通過 infer 聲明了兩個類型變量 U 和 R,分別表示對象類型中 id 和 name 屬性的類型。若類型匹配,我們就會以元組的形式返回 id 和 name 屬性的類型。

那么現在問題來了,在 PropertyType 工具類型中,如果只聲明一個類型變量 U,那結果又會是怎樣呢?下面我們來驗證一下:

type PropertyType<T> =  T extends { id: infer U, name: infer U } ? U : T

type U4 = PropertyType<User> // string | number

由以上代碼可知,U4 類型返回的是 string 和 number 類型組合成的聯合類型。為什么會返回這樣的結果呢?這是因為在協變位置上,若同一個類型變量存在多個候選者,則最終的類型將被推斷為聯合類型。

然而,在逆變位置上,若同一個類型變量存在多個候選者,則最終的類型將被推斷為交叉類型。同樣,我們來實際驗證一下:

type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer U) => void } ? U : never;

type U5 = Bar<{ a: (x: string) => void, b: (x: number) => void }>; // string & number

在以上代碼中,U5 類型返回的是 string 和 number 類型組合成的交叉類型,即最終的類型是 never 類型。

看完本文之后,相信你已經了解條件類型和 infer 的作用了。那么你能看懂 UnionToIntersection 這個工具類型的具體實現么?

type UnionToIntersection<U> = (
U extends any ? (arg: U) => void : never
) extends (arg: infer R) => void
? R
: never

責任編輯:武曉燕 來源: 全棧修仙之路
相關推薦

2022-06-05 23:28:50

TypeScripinfer類型

2024-10-14 08:31:41

泛型策略模式

2022-05-22 21:16:46

TypeScriptOmit 工具

2021-09-29 18:17:30

Go泛型語言

2022-01-05 07:07:37

Go核心設計

2009-09-25 10:03:51

Java泛型

2021-06-17 06:51:32

Java泛型Java編程

2022-04-15 09:55:59

Go 泛型Go 程序函數

2019-09-04 00:20:10

JSON泛型擦除

2021-07-01 06:47:30

Java泛型泛型擦除

2009-09-14 14:01:21

LINQ泛型數據集

2022-01-03 18:07:56

泛型場景demo

2011-06-03 08:49:54

Java

2011-04-13 09:16:55

泛型

2010-01-06 10:43:49

.NET Framew

2021-12-30 19:34:15

Java泛型JDK

2009-08-26 09:36:03

C#泛型

2024-10-28 00:40:49

Go語法版本

2020-10-20 09:53:11

代碼IDEA生成器

2024-04-23 08:23:36

TypeScript泛型Generics
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩欧美在线一区 | 国产一级视频在线观看 | 狠狠干天天干 | 日韩精品在线观看网站 | 亚洲精品视频网站在线观看 | 天天操天天摸天天干 | 亚洲国产精品视频一区 | 亚洲美女视频 | 免费99精品国产自在在线 | 亚洲精选一区二区 | 2019精品手机国产品在线 | 性视频一区| 精品一区二区三区四区在线 | 国产高清精品一区二区三区 | 欧美激情在线精品一区二区三区 | 亚州影院 | 国产一区二区三区在线免费观看 | 天天天天天操 | www性色| 亚洲成人一区 | 亚洲a视频| 91精品国产综合久久婷婷香蕉 | 天天看天天摸天天操 | 国产欧美日韩综合精品一区二区 | 二区在线观看 | 四虎成人av | 成人av免费在线观看 | 国产欧美日韩一区二区三区在线 | 在线中文字幕亚洲 | 久久大陆 | 精品欧美一区二区三区久久久 | 国产在线精品一区二区三区 | 中文字幕在线剧情 | 91精品国产综合久久婷婷香蕉 | 中文字幕 亚洲一区 | 欧美激情视频网站 | 成人影院一区二区三区 | 国产欧美二区 | 国产成人在线视频播放 | 久久手机在线视频 | 亚洲高清视频在线观看 |