TypeScript泛型

泛型提供了一種將類型參數(shù)化的能力,在其他語言中最基本的用途是定義容器類型,使得工具函數(shù)可以不必知道被操作的變量的具體類型。JavaScript 中的數(shù)組或 Promise 在 TypeScript 中都會被表述為這樣的泛型類型,例如 Promise.all 的類型定義可以寫成:

function all<T>(values: Array<T | Promise<T>>): Promise<Array<T>>

可以看到類型參數(shù)可以被用來構(gòu)造更復雜的類型,進行集合運算或嵌套。

默認情況下,因為類型參數(shù)可以是任意的類型,所以不能假定它有某些屬性或方法,也就不能訪問它的任何屬性,只有添加了約束才能遵循這個約束去使用它,同時 TypeScript 會依照這個約束限制傳入的類型:

interface Lengthwise {
  length: number
}

function logLength<T extends Lengthwise>(arg: T) {
  console.log(arg.length)
}

約束中也可以用到其他的類型參數(shù)或使用多個類型參數(shù),在下面的代碼中我們限制類型參數(shù) K 必須是 obj 的一個屬性名:

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

除了在函數(shù)上使用泛型之外,我們還可以定義泛型類型:

type Partial<T> = {
  [P in keyof T]?: T[P];
}

當定義泛型類型時我們實際上是在定義一種處理類型的「函數(shù)」,使用泛型參數(shù)去生成新的類型,這也被稱作「元編程」。例如 Partial 會遍歷傳入類型 T 的每一個屬性,返回一個所有屬性都可空的新類型:

interface Person {
  name: string
}

const a: Person = {} // 報錯 Property 'name' is missing in type '{}' but required in type 'Person'.
const b: Partial<Person> = {}

前面我們提到的 Pick 和 Extract 都是這樣的泛型類型。

在此之外 TypeScript 甚至可以在定義泛型類型時進行條件判斷和遞歸,這使得 TypeScript 的類型系統(tǒng)變成了圖靈完備的,可以在編譯階段進行任何計算。

你可能會懷疑這樣復雜的類型真的有用么?其實這些特性更多地是提供給庫開發(fā)者使用的,對于 JavaScript 社區(qū)中的 ORM、數(shù)據(jù)結(jié)構(gòu),或者是 lodash 這樣的庫來說,如此強大的類型系統(tǒng)是非常必要的,lodash 的 類型定義 行數(shù)甚至是它本身代碼的幾十倍。

如果想要簡單調(diào)試ts的特性,可以在這里TypeScript練習
在線調(diào)試。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容