TypeScript中使用泛型扩展抽象类的类型问题
问题描述
在扩展接受泛型T的抽象类TestClass时,希望ImplTestClass类中eventList属性的类型为AllowedEvents所有可能值组成的联合类型数组,但当前实现无法达到预期,求解决方法。
type EventMap = Record<string, unknown>; abstract class TestClass<T extends EventMap> { public eventList: Array<T[keyof T]>; constructor() { this.eventList = []; } } interface AllowedEvents extends EventMap { created: { time: string; userId: number; createdId: number; }, removed: { time: string; userId: number; removedId: number; } } class ImplTestClass extends TestClass<AllowedEvents> { getEventList() { return this.eventList; // 期望eventList的类型为 // ({ time: string; userId: number; createdId: number; } | { time: string; userId: number; removedId: number; }) } };
解决方案
问题根源在于EventMap的定义:Record<string, unknown>会让T[keyof T]被推断为unknown,因为unknown是所有类型的父类型,TypeScript无法保留具体的联合类型信息。以下是几种可行的修改方案:
方案1:调整EventMap的类型约束
将EventMap改为更具体的结构类型,避免用unknown抹平类型差异:
// 替换原有的EventMap定义 type EventMap = { [key: string]: object }; abstract class TestClass<T extends EventMap> { public eventList: Array<T[keyof T]>; constructor() { this.eventList = []; } }
方案2:直接在抽象类泛型中定义约束
如果不需要单独的EventMap类型,可以直接在抽象类的泛型约束里指定结构:
abstract class TestClass<T extends { [key: string]: object }> { public eventList: Array<T[keyof T]>; constructor() { this.eventList = []; } }
方案3:用工具类型显式提取值类型
先定义一个提取对象值类型的工具类型,让代码逻辑更清晰:
type ValueOf<T> = T[keyof T]; abstract class TestClass<T extends { [key: string]: object }> { public eventList: ValueOf<T>[]; constructor() { this.eventList = []; } }
以上任意方案修改后,ImplTestClass中的eventList都会被正确推断为你期望的联合类型数组:({ time: string; userId: number; createdId: number; } | { time: string; userId: number; removedId: number; })[]
内容的提问来源于stack exchange,提问作者mufasa
相关产品推荐
相关产品推荐

