这篇文章主要介绍“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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。