TypeScript如何基于构造函数参数自动推导条件泛型类型?
TypeScript泛型类自动推导泛型类型的实现方案
问题场景
你定义了如下Collection类:
// 补充代码中缺失的类型定义 type ObjectWithNumberId = { id: number; [key: string]: any }; class Collection<ID extends string | number> { // 原代码类型错误,entries应为带id的对象数组而非ID[] entries: { id: ID }[]; constructor(private readonly useStringIds: boolean) {} getIds(): ID[] { // 原代码遗漏this,修正为this.entries return this.entries.map((entry) => entry.id); } handleResults(results: ObjectWithNumberId[]) { if (this.useStringIds) { this.entries = results.map((result) => ({ ...result, id: result.id.toString(), })); } else { this.entries = results; } } }
当前使用时必须同时指定泛型类型和构造函数参数(如const c = new Collection<string>(true);),希望仅传入构造函数参数,让TypeScript自动推导对应的泛型类型。
解决方案
TypeScript无法直接从构造函数的boolean参数推导类的泛型,但可以通过静态工厂方法实现自动推导。利用静态方法的参数字面量类型,让TS根据传入的useStringIds值自动推断返回实例的泛型类型:
修改后的完整代码
type ObjectWithNumberId = { id: number; [key: string]: any }; class Collection<ID extends string | number> { entries: { id: ID }[]; // 将构造函数设为private,强制通过工厂方法创建实例 private constructor(private readonly useStringIds: boolean) {} getIds(): ID[] { return this.entries.map((entry) => entry.id); } handleResults(results: ObjectWithNumberId[]) { if (this.useStringIds) { this.entries = results.map((result) => ({ ...result, id: result.id.toString(), })) as { id: ID }[]; } else { this.entries = results as { id: ID }[]; } } // 静态工厂方法,根据参数类型自动推导泛型 static create<T extends boolean>(useStringIds: T): Collection<T extends true ? string : number> { return new Collection(useStringIds); } }
使用示例
// 自动推导为Collection<string> const stringCollection = Collection.create(true); stringCollection.handleResults([{ id: 1, name: "test" }]); const stringIds = stringCollection.getIds(); // 类型为string[] // 自动推导为Collection<number> const numberCollection = Collection.create(false); numberCollection.handleResults([{ id: 2, name: "demo" }]); const numberIds = numberCollection.getIds(); // 类型为number[]
说明
- 将构造函数设为
private,避免直接通过new创建实例,强制使用工厂方法保证类型推导的正确性。 - 静态工厂方法
create的参数使用字面量类型T extends boolean,通过条件类型T extends true ? string : number将参数值映射为对应的泛型类型。 - 修正了原代码中
entries类型定义错误、getIds方法遗漏this的问题,确保类型逻辑自洽。
内容的提问来源于stack exchange,提问作者755
相关产品推荐
相关产品推荐

