您好,登錄后才能下訂單哦!
這篇文章主要介紹“TypeScript泛型推斷怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“TypeScript泛型推斷怎么實現”文章能幫助大家解決問題。
用一個枚舉來定義Animal
的類型
enum EAnimalType { dog = 'dog', cat = 'cat', bird = 'bird', }
定義不同類型的動物有不同的能力類型
type Dog = { /** 大叫 */ shoutLoudly: () => void; } type Cat = { say: () => void; } type Bird = { /** 飛 */ fly: () => void; }
定義一個動物的映射類型
type AnimalMap = { [EAnimalType.dog]: Dog; [EAnimalType.cat]: Cat; [EAnimalType.bird]: Bird; }
/** * 定義一個工廠,用來創建具體動物的實例 * @returns 返回動物的實例 */ function createAnimalFactory<T extends EAnimalType>(): IAnimal<T> { // TODO 根據業務具體實現 return {} as IAnimal<T>; } // 根據泛型創建狗狗的實例 const dog = createAnimalFactory<EAnimalType.dog>(); dog.shoutLoudly(); // 根據泛型創建鳥的實例 const bird = createAnimalFactory<EAnimalType.bird>(); bird.fly()
接著我們創建一個interface
來定義動物基礎接口
export interface IAnimal<T extends EAnimalType> extends IAnimalExtra<T> { id: number; // 編號 name: string; // 名稱 type: T; // 類型 }
我們看到IAnimal
接口繼承了IAnimalExtra
接口,我們想的是通過泛型T
來動態推導出真實的類型。讓我們來看看IAnimalExtra
接口怎么寫
寫IAnimalExtra
接口
export type IAnimalExtra<T extends EAnimalType> { [c in keyof AnimalMap[T]]: AnimalMap[T][c]; }
我們這樣寫,發現調試控制臺報了很多錯,具體分析了下錯誤,接口不支持這種功能。接著我們嘗試,改成type
試一下。
最后用type
去替代 IAnimalExtra
export type IAnimalExtra<T extends EAnimalType> = { [c in keyof AnimalMap[T]]: AnimalMap[T][c]; }
我們用type
,果然不不錯了,證明我們的思路是對的。乍一看,寫的怎么復雜[c in keyof AnimalMap[T]]: AnimalMap[T][c];
不要怕,我們先具體分析一下這段代碼,就很好理解了。
先看AnimalMap[T]
,可以理解從AnimalMap
類型中獲取對應的類型,近似js中從對象取值
keyof
接受一個Object,生成Object的key的字符串的union(聯合)
in
可以遍歷枚舉類型,類似 for...in
整體的功能就是根據泛型T,獲取AnimalMap
中的某個類型,遍歷。
extends IAnimalExtra<T>
報錯了
在我們最終認為可以的情況下,發現有報錯了,內容為【接口只能擴展對象類型或對象類型與靜態已知成員的交集】
在我們嘗試了多次之后,發現Interface
怎么也滿足不了需求,接著我們都換成type去試試。
export type IAnimal<T extends EAnimalType> = IAnimalExtra<T> & { id: number; // 編號 name: string; // 名稱 type: T; // 類型 }
這里我們用了&
交叉類型類合并接口的類型。
換成type之后,已能完全滿足我們的需求,能根據泛型推斷出我們想要的類型。
/** * 動物枚舉 */ export enum EAnimalType { dog = 'dog', cat = 'cat', bird = 'bird', } type Dog = { /** 大叫 */ shoutLoudly: () => void; } type Cat = { say: () => void; } type Bird = { /** 飛 */ fly: () => void; } export type AnimalMap = { [EAnimalType.dog]: Dog; [EAnimalType.cat]: Cat; [EAnimalType.bird]: Bird; } export type IAnimalExtra<T extends EAnimalType> = { [c in keyof AnimalMap[T]]: AnimalMap[T][c]; } export type IAnimal<T extends EAnimalType> = IAnimalExtra<T> & { id: number; // 編號 name: string; // 名稱 type: T; // 類型 } /** * 定義一個工廠,用來創建具體動物的實例 * @returns 返回動物的實例 */ function createAnimalFactory<T extends EAnimalType>(): IAnimal<T> { // TODO 根據業務具體實現 return {} as IAnimal<T>; } // 根據泛型創建狗狗的實例 const dog = createAnimalFactory<EAnimalType.dog>(); dog.shoutLoudly(); // 根據泛型創建鳥的實例 const bird = createAnimalFactory<EAnimalType.bird>(); bird.fly();
關于“TypeScript泛型推斷怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。