【TS】506- TypeScript 交叉類型
- 2020 年 3 月 2 日
- 筆記
一、簡介
TypeScript 交叉類型是將多個類型合併為一個類型。這讓我們可以把現有的多種類型疊加到一起成為一種類型,它包含了所需的所有類型的特性。
interface IPerson { id: string; age: number; } interface IWorker { companyId: string; } type IStaff = IPerson & IWorker; const staff: IStaff = { id: 'E1006', age: 33, companyId: 'EXE' }; console.dir(staff)
在上面示例中,我們首先為 IPerson 和 IWorker 類型定義了不同的成員,然後通過 &
運算符定義了 IStaff 交叉類型,所以該類型同時擁有 IPerson 和 IWorker 這兩種類型的成員。那麼現在問題來了,假設在合併多個類型的過程中,剛好出現某些類型存在相同的成員,但對應的類型又不一致,比如:
interface X { c: string; d: string; } interface Y { c: number; e: string } type XY = X & Y; type YX = Y & X; let p: XY; let q: YX;
在上面的代碼中,接口 X 和接口 Y 都含有一個相同的成員 c,但它們的類型不一致。對於這種情況,此時 XY 類型或 YX 類型中成員 c 的類型是不是可以是 string
或 number
類型呢?比如下面的例子:
p = { c: 6, d: "d", e: "e" };

q = { c: "c", d: "d", e: "e" };

為什麼接口 X 和接口 Y 混入後,成員 c 的類型會變成 never
呢?這是因為混入後成員 c 的類型為 string&number
,即成員 c 的類型既是 string
類型又是number
類型。很明顯這種類型是不存在的,所以混入後成員 c 的類型為 never
。
在上面示例中,剛好接口 X 和接口 Y 中內部成員 c 的類型都是基本數據類型,那麼如果是非基本數據類型的話,又會是什麼情形。我們來看個具體的例子:
interface D { d: boolean; } interface E { e: string; } interface F { f: number; } interface A { x: D; } interface B { x: E; } interface C { x: F; } type ABC = A & B & C; let abc: ABC = { x: { d: true, e: 'semlinker', f: 666 } }; console.log('abc:', abc);
以上代碼成功運行後,控制台會輸出以下結果:

由上圖可知,在混入多個類型時,若存在相同的成員,且成員類型為非基本數據類型,那麼是可以成功合併。前面我們已經介紹了 TypeScript 交叉類型相關的知識,最後我們再來舉一個實際的使用示例。
二、使用示例
在實際項目開發過程中,我們經常需要開發一些功能函數,為了保證函數的靈活性和可復用性,這些函數往往會定義一些輸入參數,而這些參數根據是否必填,又可分為必填參數和可選參數。當必填參數和可選參數有大部分參數是相同的情況下,我們就可以利用 TypeScript 交叉類型來解決復用問題。好了,廢話不多說,直接看個示例:
ArgBase 接口
export interface ArgBase<T> { name?: string; description?: string; hidden?: boolean; parse: ParseFn<T>; default?: T | (() => T); input?: string; options?: string[]; }
RequiredArg 接口
export type RequiredArg<T> = ArgBase<T> & { required: true; value: T; }
OptionalArg 接口
export type OptionalArg<T> = ArgBase<T> & { required: false; value?: T; }
顧名思義,ArgBase 接口是基礎參數接口,它是 RequiredArg 和 OptionalArg 接口的公共部分。示例代碼中,RequiredArg 和 OptionalArg 的差異就是 required 字段和與之對應的 value 值。通過交叉類型,可以讓我們更好地進行代碼復用,並方便地實現把多種類型疊加到一起成為一種新的類型。
三、參考資源
- tslang-advanced-types
- typescript-intersection-types