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