如何在TypeScript中根据泛型属性选择对应类型?
如何根据泛型属性选择类型?
问题场景
现有如下TypeScript代码,所有动物对象都包含type属性(对应AnimalType枚举),其余属性因种类而异。需要实现一个泛型类型Animal<T>,使得Animal<AnimalType.DOG>等价于typeof dog,但当前嵌套条件类型的实现过于冗长:
enum AnimalType { DOG, CAT, FROG, SNAKE, } const dog = { type: AnimalType.DOG, legs: 4, } const cat = { type: AnimalType.CAT, tail: 1, } const frog = { type: AnimalType.FROG, canSwim: true, tail: 0, } const snake = { type: AnimalType.SNAKE, tail: 'looong', age: 2, } // 现有冗长实现 type Animal<T extends AnimalType> = T extends AnimalType.DOG ? typeof dog : T extends AnimalType.CAT ? typeof cat : T extends AnimalType.FROG ? typeof frog : T extends AnimalType.SNAKE ? typeof snake : unknown
更优解决方案
方案一:利用内置Extract工具类型
先定义所有动物的联合类型,再通过Extract筛选出对应type属性的成员:
// 定义所有动物的联合类型 type AllAnimals = typeof dog | typeof cat | typeof frog | typeof snake; // 提取type属性等于T的动物类型 type Animal<T extends AnimalType> = Extract<AllAnimals, { type: T }>;
说明:Extract是TypeScript内置工具类型,作用是从第一个联合类型参数中,提取出可赋值给第二个类型参数的成员。这里通过{ type: T }作为筛选条件,精准匹配对应枚举值的动物类型。
方案二:构建枚举-类型映射表
直接创建一个以枚举值为键、对应动物类型为值的映射类型,通过索引访问获取目标类型:
// 构建枚举到类型的映射表 type AnimalMap = { [AnimalType.DOG]: typeof dog; [AnimalType.CAT]: typeof cat; [AnimalType.FROG]: typeof frog; [AnimalType.SNAKE]: typeof snake; }; // 通过索引访问获取对应类型 type Animal<T extends AnimalType> = AnimalMap[T];
说明:这种方式逻辑直观,维护成本低——新增动物种类时,只需在AnimalMap中添加一行键值对即可,可读性更强。
验证效果
两种方案都能实现预期效果:
// 类型等价于typeof dog type DogType = Animal<AnimalType.DOG>; // 类型等价于typeof snake type SnakeType = Animal<AnimalType.SNAKE>;
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

