这篇文章主要介绍“TypeScript泛型推断怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“TypeScript泛型推断怎么实现”文章能帮助大家解决问题。
基础类型准备
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接口怎么写
export type IAnimalExtra<T extends EAnimalType> {
[c in keyof AnimalMap[T]]: AnimalMap[T][c];
}
我们这样写,发现调试控制台报了很多错,具体分析了下错误,接口不支持这种功能。接着我们尝试,改成type试一下。
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中的某个类型,遍历。

在我们最终认为可以的情况下,发现有报错了,内容为【接口只能扩展对象类型或对象类型与静态已知成员的交集】
所有内容都基于type 实现
在我们尝试了多次之后,发现Interface怎么也满足不了需求,接着我们都换成type去试试。
export type IAnimal<T extends EAnimalType> = IAnimalExtra<T> & {
id: number; // 编号
name: string; // 名称
type: T; // 类型
}这里我们用了&交叉类型类合并接口的类型。
换成type之后,已能完全满足我们的需求,能根据泛型推断出我们想要的类型。
完整Demo
/**
* 动物枚举
*/
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泛型推断怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注天达云行业资讯频道,小编每天都会为大家更新不同的知识点。