TypeScript中如何正确推断继承基类时传入的具体泛型类型
问题描述
请参考如下代码:
type secondaryObjectConstraint = { [key: string]: number } abstract class Base<TObject extends object, TSecondaryObject extends secondaryObjectConstraint> {} type secondaryObjectType = { myProp: number } class ExtendedObject extends Base<{}, secondaryObjectType> {} type inferSecondaryObject<M extends Base<any, any>> = M extends Base<any, infer TSecondaryObject> ? TSecondaryObject : never; const a: inferSecondaryObject<ExtendedObject> = {};
上述示例中,变量a被推断的类型为secondaryObjectConstraint,而非预期的精确类型secondaryObjectType。
问题原因
该现象由TypeScript结构化类型系统的泛型处理规则导致:
- 如果泛型参数仅出现在类的泛型约束声明中,完全没有参与类的实例成员(属性、方法)定义,TypeScript不会保留传入该泛型位置的具体类型,会直接将其替换为泛型的约束边界类型。
- 示例中
Base是空抽象类,TSecondaryObject没有被任何类结构引用,因此编译阶段传入的secondaryObjectType被直接替换为约束secondaryObjectConstraint,后续类型推断自然无法拿到精确类型。
修复方案
只需让泛型参数参与到Base类的结构定义中即可,最通用的做法是添加类型占位属性,不需要实际赋值使用,仅在类型层面保留泛型信息,不会产生额外运行时开销:
type secondaryObjectConstraint = { [key: string]: number } abstract class Base<TObject extends object, TSecondaryObject extends secondaryObjectConstraint> { // 可选占位属性,仅用于绑定泛型到类结构 _tObject?: TObject; _tSecondaryObject?: TSecondaryObject; } type secondaryObjectType = { myProp: number } class ExtendedObject extends Base<{}, secondaryObjectType> {} type inferSecondaryObject<M extends Base<any, any>> = M extends Base<any, infer TSecondaryObject> ? TSecondaryObject : never; // 此时a的类型被正确推断为secondaryObjectType,赋值空对象会触发缺少myProp属性的类型报错 const a: inferSecondaryObject<ExtendedObject> = {};
内容的提问来源于stack exchange,提问作者Adam Baranyai
相关产品推荐
相关产品推荐

