TypeScript 給 JavaScript 加了套靜態類型系統。其中,JavaScript 中的數組、對象等聚合多個元素的類型在 TypeScript 中對應的是索引類型。
比如這就是一個索引類型:
type obj = { name: string; age: number; gender: boolean; }
索引類型可以添加修飾符 readonly(只讀)、?(可選):
type obj = { readonly name: string; age?: number; gender: boolean; }
我們知道,TypeScript 支持類型編程,也就是對類型參數(范型)做各種運算,產生新的類型:
type IsString= T extends string ? true: false;
那么對于索引類型,如何做運算并產生新的類型呢?
答案是映射類型。
映射類型
映射類型就是用于構造新的索引類型的。
比如這個 Record 類型:
type Record< K extends string | number | symbol, T> = { [P in K]: T; }
Record 類型構造了一個 key 為 stirng 或 number 或 symbol,而 value 為類型 T 的索引類型。它是 TS 內置的高級類型。
在構造新的索引類型的過程中,還可以做加上一些修飾符。
比如 ReadOnly:
type Readonly= { readonly [Key in keyof T]: T[Key]; }
它創建了一個新的索引類型,在原來索引類型的每個屬性上加上了 readonly 的修飾:
比如 Partial:
type Partial= { [Key in keyof T]?: T[Key] }
它創建了一個新的索引類型,在原來索引類型的每個屬性上加上了 ? 的修飾:
可以加上,當然也可以去掉:
去掉可選(?):
type Required= { [Key in keyof T]-?: T[Key] }
去掉 readonly:
type NotReadOnly= { -readonly [Key in keyof T]: T[Key] }
過完這些例子,映射類型能干什么就比較清楚了:
映射類型可以生成新的索引類型,在生成過程中可以加上或去掉 readonly、? 的修飾符。內置的 Record、ReadOnly、Required、Partial 等類型都是映射類型。
但是,現在的映射類型還是有局限性的,不能對索引名做修改、過濾等操作,功能還不夠強。
如果想實現過濾、轉換,那就得用到映射類型的重映射了。
重映射
重映射就是在索引后加一個 as 語句,表明索引轉換成什么,它可以用來對索引類型做過濾和轉換。
比如過濾出類型為 string 的索引:
type FilterString= { [Key in keyof T as T[Key] extends string ? Key: never]: T[Key]; }
返回 never 代表過濾掉,否則保留。
還可以對索引做轉換,比如修改索引名,加上 get:
type Getters> = { [Key in keyof T as `get${Capitalize }`]: T[Key]; }
T extends xxx 是給類型參數的約束,表示只能傳入這種類型。這里的 Record 類型是生成索引類型的,我們上面介紹過,所以 T extends Record 就是約束了這里只能傳入索引類型。
as 后面是把索引轉換成什么,我們是在原來的基礎上做了修改,加上了 get,并且后面內容首字母大寫,這個 Capitalize 也是 TS 內置的類型。
效果如下:
這兩個例子分別說明了重映射 as 可以用來做索引類型的過濾和轉換,可以對索引類型做更靈活的編程。
比如,實現 key 和 value 的互換:
type Flip> = { [Key in keyof T as `${T[Key]}`]: Key }
支持重映射之后,映射類型可以對索引類型做更多的修改。
總結
TypeScript 通過索引類型來表示有多個元素的聚合類型,比如數組、對象等。
TS 支持類型編程,也就是對類型參數做各種運算然后返回新的類型。對索引類型當然也可以做運算,對應的類型就是映射類型。
映射類型在生成新的索引類型的過程中,還可以加上或去掉 readonly、?的修飾符。內置的 Record、Required、Partial、ReadOnly 都是映射類型。
如果想對索引類型做進一步的過濾和轉換,就需要用到 as 的重映射,它可以對索引做修改(當索引為 never 就代表過濾掉該索引)。
會用索引類型是只是基礎,會用映射類型和重映射就是進階內容了,這部分可以寫出很多復雜的類型邏輯,屬于類型體操的范疇。
原文地址:https://mp.weixin.qq.com/s/Im52Qt1gt5eX7DIPZxfLpQ