亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

TypeScript infer 關鍵字

本節要介紹的 infer 關鍵字有些難理解,我們來通過一個類比來幫助理解。

語句 let num 中,通過 let 來聲明了一個變量,那怎樣聲明一個不確定的類型變量呢? 答案是使用 infer 關鍵字,infer R 就是聲明了一個類型變量 R。

1. 慕課解釋

在條件類型表達式中,可以在 extends 條件語句中使用 infer 關鍵字來聲明一個待推斷的類型變量。

2. 通過 ReturnType 理解 infer

infer 相對比較難理解,我們先看下 TypeScript 一個內置工具類型 ReturnType 。

  • ReturnType<T> – 獲取函數返回值類型。
const add = (x:number, y:number) => x + y
type t = ReturnType<typeof add> // type t = number

代碼解釋:

通過 ReturnType 可以得到函數 add() 的返回值類型為 number 類型。但要注意不要濫用這個工具類型,應盡量多的手動標注函數返回值類型。

來看一下 ReturnType 的實現源碼:

/**
 * Obtain the return type of a function type
 */
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any

infer 的作用是讓 TypeScript 自己推斷,并將推斷的結果存儲到一個類型變量中,infer 只能用于 extends 語句中。

再來看 ReturnType 的實現:如果 T 滿足約束條件 (...args: any) => any,并且能夠賦值給 (...args: any) => infer R,則返回類型為 R,否則為 any 類型。

繼續看幾個例子:

type T0 = ReturnType<() => string>        // string
type T1 = ReturnType<(s: string) => void> // void
type T2 = ReturnType<<T>() => T>          // unknown

代碼解釋:

分別可以得到 type T0 = string type T1 = void type T2 = unknown,只要滿足約束條件 (...args: any) => any,TypeScript 推斷出函數的返回值,并借助 infer 關鍵字將其儲存在類型變量 R 中,那么最終得到返回類型 R。

3. 借助 infer 實現元組轉聯合類型

借助 infer 可以實現元組轉聯合類型,如:[string, number] -> string | number

type Flatten<T> = T extends Array<infer U> ? U : never

type T0 = [string, number]
type T1 = Flatten<T0> // string | number

代碼解釋:

第 1 行,如果泛型參數 T 滿足約束條件 Array<infer U>,那么就返回這個類型變量 U。

第 3 行,元組類型在一定條件下,是可以賦值給數組類型,滿足條件:

type TypeTuple = [string, number] 
type TypeArray = Array<string | number>

type B0 = TypeTuple extends TypeArray ? true : false // true

第 4 行,就可以得到 type T1 = string | number。

4. 小結

infer 理解起來比較抽象,一定要親手寫一下本節中的例子。借助條件類型的 infer 關鍵字來推斷類型,可以實現一些比如聯合類型轉交叉類型、聯合類型轉元組的操作,有興趣的可以了解一下。