TypeScript带protected构造函数的泛型类正确继承问题求助
解决带protected构造函数的泛型基类继承与静态工厂类型推断问题
我需要实现一个带有protected构造函数的泛型基类BaseClass,核心需求如下:
- 只能通过静态工厂方法
create实例化,该方法要验证参数s与传入函数的s参数类型匹配,并自动完成类的泛型参数化 - 支持子类继承
BaseClass - 调用子类的
create方法时,TypeScript需自动推断出子类的泛型类型,不需要重写create方法或显式指定类型
但当前代码在调用DerivedClass.create时触发类型错误:
The 'this' context of type 'typeof DerivedClass' is not assignable to method's 'this' of type 'new (fn: FnType<undefined, any>, s: { v: string; }) => BaseClass<undefined, any>'. Cannot assign a 'protected' constructor type to a 'public' constructor type.
同时,create方法返回的实例类型被推断为DerivedClass<unknown, unknown>,完全不符合预期。
原代码如下:
type FnType<A, S> = (params: { a: A, s: S, anotherParam: any }) => number; class BaseClass<A = undefined, S = any> { protected fn: FnType<A, S>; protected s: S; protected constructor(fn: FnType<A, S>, s: S) { this.fn = fn; this.s = s; } static create< T extends new (fn: FnType<undefined, any>, s: S) => BaseClass, Fn extends FnType<undefined, any>, S = Parameters<Fn>[0]["s"], >( this: T, fn: Fn, s: Parameters<Fn>[0]["s"] ) { const instance = new this(fn, s) as InstanceType<T>; return instance; } } class DerivedClass<A, S> extends BaseClass<A, S> { someMethod () { console.log('1'); } } const childInstance = DerivedClass.create( (params: { a: number, s: { v: string }, anotherParam: any }) => 1, { v: 'Hello!'}, );
错误根源分析
- 原
create方法对T的约束要求构造函数是public可见的,但BaseClass及其子类的构造函数都是protected,类型系统不允许这种赋值 - 泛型参数的推导逻辑存在缺陷,无法从传入的
Fn中正确提取A和S类型,导致子类实例的泛型参数被推断为unknown
修复后的代码
type FnType<A, S> = (params: { a: A; s: S; anotherParam: any }) => number; class BaseClass<A = undefined, S = any> { protected fn: FnType<A, S>; protected s: S; protected constructor(fn: FnType<A, S>, s: S) { this.fn = fn; this.s = s; } static create< Fn extends FnType<any, any>, A = Parameters<Fn>[0]["a"], S = Parameters<Fn>[0]["s"] >( this: { new(fn: FnType<A, S>, s: S): BaseClass<A, S> }, fn: Fn, s: S ): BaseClass<A, S> { return new this(fn, s) as BaseClass<A, S>; } } class DerivedClass<A, S> extends BaseClass<A, S> { someMethod() { console.log('1'); } } // 自动推断 childInstance 类型为 DerivedClass<number, { v: string; }> const childInstance = DerivedClass.create( (params: { a: number; s: { v: string }; anotherParam: any }) => 1, { v: 'Hello!' }, ); // 类型验证生效:传入不匹配的s会报错 // const invalidInstance = DerivedClass.create( // (params: { a: number; s: { v: string }; anotherParam: any }) => 1, // { v: 123 }, // 类型错误:number 不能赋值给 string // );
代码说明
- 重新定义
create方法的this类型约束:使用{ new(fn: FnType<A, S>, s: S): BaseClass<A, S> },这种签名可以匹配带有protected构造函数的类(TypeScript对protected构造的类的构造函数类型有特殊处理) - 优化泛型推导逻辑:直接从传入的
Fn中提取A和S类型,分别对应函数参数的a和s字段,确保类的泛型参数与函数参数类型完全关联 - 保留
protected构造函数,保证类只能通过create方法实例化 - 子类继承后无需修改
create方法,调用时TypeScript会自动推断出DerivedClass<number, { v: string; }>类型 - 类型验证功能正常:如果传入的
s与函数中的s类型不匹配,会立刻触发TypeScript错误
内容的提问来源于stack exchange,提问作者Alexander Paschenko
相关产品推荐
相关产品推荐

