You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中为何无法推断泛型父类Closure的类型参数?

问题原因分析

当你定义非泛型类 B 继承自泛型父类 Closure<A> 时,TypeScript 并不会将父类的泛型参数信息保留在子类的类型元数据中。虽然 B 的实例确实是 Closure<A> 的子类型,但在条件类型 T extends Closure<infer U> 的匹配过程中,TypeScript 无法从具体子类 B 的类型信息中回溯推断出父类的泛型参数 A,最终只能返回默认的 unknown。

而 BaseOf<Closure<A>> 能正确得到 A,是因为 Closure<A> 是显式的泛型实例类型,直接携带了 Base 参数的完整类型信息,没有经过子类的类型擦除。

解决方案

方案一:在父类中添加类型标记属性

在 Closure 类中添加一个仅用于类型推断的虚拟属性,显式存储 Base 类型,让子类继承后保留该类型信息:

abstract class Closure<Base> {
    // 虚拟属性,仅用于类型标记,无需实现
    readonly __baseType!: Base;
}

interface A {
    foo(args: { one: string, two: number }): void
}

class B extends Closure<A> implements A {
    foo(args: { one: string, two: number }) { }
}

type BaseOf<T extends Closure<unknown>> = T['__baseType'];
type b = BaseOf<B>; // 现在得到 A 类型

方案二:将子类定义为泛型类

如果允许子类是泛型的,可以显式绑定 Base 参数,保留泛型信息:

abstract class Closure<Base> { }

interface A {
    foo(args: { one: string, two: number }): void
}

// 显式将 Base 作为泛型参数,默认值设为 A
class B<Base = A> extends Closure<Base> implements A {
    foo(args: { one: string, two: number }) { }
}

type BaseOf<T extends Closure<unknown>> = T extends Closure<infer U> ? U : never;
type b = BaseOf<B>; // 得到 A 类型

方案三:从构造函数的实例类型推断

如果传入的是类的构造函数类型(比如 typeof B),可以调整 BaseOf 直接从实例类型推断:

abstract class Closure<Base> { }

interface A {
    foo(args: { one: string, two: number }): void
}

class B extends Closure<A> implements A {
    foo(args: { one: string, two: number }) { }
}

type BaseOf<T> = InstanceType<T> extends Closure<infer U> ? U : never;
type b = BaseOf<typeof B>; // 得到 A 类型

内容的提问来源于stack exchange,提问作者Sebastian Nemeth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:45:41