TypeScript泛型推断怎么实现

发布时间:2022-08-17 16:12:40 作者:iii
来源:亿速云 阅读:174

这篇文章主要介绍“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];
}

TypeScript泛型推断怎么实现

我们这样写,发现调试控制台报了很多错,具体分析了下错误,接口不支持这种功能。接着我们尝试,改成type试一下。

export type IAnimalExtra<T extends EAnimalType> = {
  [c in keyof AnimalMap[T]]: AnimalMap[T][c];
}

我们用type,果然不不错了,证明我们的思路是对的。乍一看,写的怎么复杂[c in keyof AnimalMap[T]]: AnimalMap[T][c]; 不要怕,我们先具体分析一下这段代码,就很好理解了。

整体的功能就是根据泛型T,获取AnimalMap中的某个类型,遍历。

TypeScript泛型推断怎么实现

在我们最终认为可以的情况下,发现有报错了,内容为【接口只能扩展对象类型或对象类型与静态已知成员的交集】

所有内容都基于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泛型推断怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

推荐阅读:
  1. TypeScript入门-泛型
  2. 前端深入理解Typescript泛型概念

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

typescript

上一篇:Python常用图像形态学操作实例分析

下一篇:SpringBoot怎么配置和切换Tomcat

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》