如何为接收基类并返回指定泛型子类的TS函数添加正确类型?
类型化动态子类生成函数的解决方案
需求背景
需要将给定的JavaScript代码转换为TypeScript,为makeSubclassA添加正确的类型定义:
- 所有传入
makeSubclassA的BaseClass必须继承自RootBaseClass RootBaseClass及所有子类都包含两个泛型参数<R extends object, P extends object>makeSubclassA固定使用RawA和ProcessedA作为泛型参数,无需外部传入
完整类型化代码
class RootBaseClass<R extends object, P extends object> { constructor() {} process(raw: R): P { throw new Error('Not implemented.') } // 其他从URL获取数据、调用process并保存到数据库的方法 } // SubclassA专属的原始数据和处理后数据类型 interface RawA { F1: string; F2: string; } interface ProcessedA { name: string; age: number; } // 类型化的makeSubclassA函数 function makeSubclassA< TBase extends new <R extends object, P extends object>() => RootBaseClass<R, P> >(BaseClass: TBase) { // 断言BaseClass可以实例化为RawA和ProcessedA参数的版本 return class SubclassA extends (BaseClass as new () => RootBaseClass<RawA, ProcessedA>) { process(raw: RawA): ProcessedA { return { name: raw.F1, age: parseInt(raw.F2) }; } } as new () => (InstanceType<TBase> extends RootBaseClass<any, any> ? Omit<InstanceType<TBase>, 'process'> & { process(raw: RawA): ProcessedA } : never); } // 自定义基类,继承自RootBaseClass class SomeBaseClass<R extends object, P extends object> extends RootBaseClass<R, P> { // 重写RootBaseClass的部分方法 } // 生成SubclassA,类型为SomeBaseClass<RawA, ProcessedA>的子类 const SubclassA = makeSubclassA(SomeBaseClass); // 实例化时类型完全正确,process方法参数和返回值都被约束 const instance = new SubclassA(); instance.process({ F1: "Alice", F2: "30" }); // 正确,返回ProcessedA类型
关键类型说明
- 泛型约束
TBase:确保传入的BaseClass是一个能生成RootBaseClass子类实例的泛型构造函数,保证类型合法性。 - 类型断言与返回类型处理:通过
as new () => RootBaseClass<RawA, ProcessedA>让TS识别子类继承的是固定参数版本的基类;返回类型通过Omit<InstanceType<TBase>, 'process'> & { process(raw: RawA): ProcessedA },保留基类原有方法,同时覆盖process方法的类型定义。 - 实例类型正确性:
SubclassA的实例会自动拥有SomeBaseClass的所有方法,且process方法被严格约束为RawA入参、ProcessedA返回值。
内容的提问来源于stack exchange,提问作者Abbas Mashayekh
相关产品推荐
相关产品推荐

