如何无需类型断言从构造函数参数推断Resolver.resolve返回类型
解决方案:无需类型断言的类型推断优化
问题核心是原ConstructorMap的递归约束让TypeScript无法精准追踪每个构造函数对应的Model泛型参数,我们可以通过调整Resolver的泛型定义和resolve方法的返回类型来解决:
// 保留原Model、FooModel、BarModel定义不变 abstract class Model<T> { public readonly value: T; public constructor(value: T) { this.value = value; } } class FooModel extends Model<{ x: number; y: number }> { public constructor() { super({ x: 1, y: 2 }); } } class BarModel extends Model<{ name: string }> { public constructor() { super({ name: 'bar' }); } } // 修改Resolver的泛型定义和resolve方法 class Resolver<T extends Record<string, new () => Model<any>>> { private readonly constructors: T; public constructor(constructors: T) { this.constructors = constructors; } public resolve<K extends keyof T>(key: K): T[K] extends new () => Model<infer U> ? Model<U> : never { const constructor = this.constructors[key]; return new constructor(); // 此处类型自动推断正确,无需断言 } } // 测试代码 const resolver = new Resolver({ FooModel, BarModel, }); const foo = resolver.resolve('FooModel'); // 类型为Model<{ x: number; y: number }> console.log(foo.value.x); // 类型提示正常 const bar = resolver.resolve('BarModel'); // 类型为Model<{ name: string }> console.log(bar.value.name); // 类型提示正常
原理说明
- 去掉了原有的
ConstructorMap递归约束,直接让Resolver的泛型T继承Record<string, new () => Model<any>>,明确每个属性都是无参构造的Model子类。 - 在
resolve方法的返回类型中,使用条件类型T[K] extends new () => Model<infer U> ? Model<U> : never,TypeScript会自动根据传入的K(构造函数名称),提取对应构造函数返回的Model实例的泛型参数U,从而精准推断返回值类型。 - 此时
new constructor()的返回值会被TypeScript正确关联到对应的Model<U>类型,无需额外断言。
内容的提问来源于stack exchange,提问作者hiroiku
相关产品推荐
相关产品推荐

