TypeScript高級類型-Partial

TypeScript高級類型-Partial

預備知識:

TypeScript類型系統
接口
泛型

先來看一下 Partial 類型的定義

/**
 * Make all properties in T optional
 */
type Partial<T> = {
    [P in keyof T]?: T[P];
};

假設我們有一個定義 user 的接口,如下

interface IUser {
  name: string
  age: number
  department: string
}

經過 Partial 類型轉化後得到

type optional = Partial<IUser>

// optional的結果如下
type optional = {
    name?: string | undefined;
    age?: number | undefined;
    department?: string | undefined;
}

那麼 Partial<T> 是如何實現類型轉化的呢?

  1. 遍歷入參 T ,獲得每一對 key, value

  2. 將每一對中的 key 變爲可選,即添加 ?

  3. 希望得到的是由 key, value 組成的新類型

以上對應到 TypeScript 中是如何實現的呢?

對照最開始 Partial 的類型定義,能夠捕捉到以下重要信息

  • keyof 是幹什麼的?

  • in 是幹什麼的?

  • [P in keyof T] 中括號是幹什麼的?

  • ? 是將該屬性變爲可選屬性

  • T[P] 是幹什麼的?

keyof

keyof,即 索引類型查詢操作符,我們可以將 keyof 作用於泛型 T 上來獲取泛型 T 上的所有 public 屬性名構成的 聯合類型

注意:"public、protected、private"修飾符不可出現在類型成員上

例如:

type unionKey = keyof IUser

// unionKey 結果如下,其獲得了接口類型 IUser 中的所有屬性名組成的聯合類型
type unionKey = "name" | "age" | "department"

in

我們需要遍歷 IUser ,這時候 映射類型就可以用上了,其語法爲 [P in Keys]

  • P:類型變量,依次綁定到每個屬性上,對應每個屬性名的類型
  • Keys:字符串字面量構成的聯合類型,表示一組屬性名(的類型),可以聯想到上文 keyof 的作用

上述問題中 [P in keyof T] 中括號是幹什麼的?這裏也就很清晰了。

T[P]

我們可以通過 keyof 查詢索引類型的屬性名,那麼如何獲取屬性名對應的屬性值類型呢?

這裏就用到了 索引訪問操作符,與 JavaScript 種訪問屬性值的操作類似,訪問類型的操作符也是通過 [] 來訪問的,即 T[P],其中”中括號“中的 P[P in keyof T] 中的 P 相對應。

例如

type unionKey = keyof IUser // "name" | "age" | "department"

type values = IUser[unionKey] // string | number 屬性值類型組成的聯合類型

最後我們希望得到的是由多個 key, value 組成的新類型,故而在 [P in keyof T]?: T[P]; 外部包上一層大括號。

到此我們解決遇到的所有問題,只需要逐步代入到 Partial 類型定義中即可。


總結:

  1. 針對高級類型的編寫,我們可以嘗試將其以 JavaScript 的代碼方式表述出來,然後使用 TypeScript 對其進行實現。
  2. 在每一個小步驟中遇到不懂的,可以結合最後的結果進行比對(比如本文中 Partial 的類型定義),發現問題點在哪裏,然後針對性查證並解決。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章