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

TypeScript父子类继承:实现子实例对应父类类型与解决循环默认类型问题

解决方案

要解决循环默认类型错误并让TypeScript正确识别child.parent的类型,我们需要重构泛型约束逻辑,避免循环默认值,同时建立清晰的类型依赖链条:

修改后的完整代码

Parent 与 SubParent 类

export class Parent<Self extends Parent<Self>> {
    protected readonly m_child: Child<Self>;

    protected constructor(builder: new (p: Self) => Child<Self>) {
        this.m_child = new builder(this as Self);
    }

    public static init() {
        return new Parent(Child) as Parent<Parent<never>>;
    }

    public get child(): Child<Self> {
        return this.m_child;
    }

    /**
     * Parent actions
     */
}

export class SubParent<Self extends SubParent<Self>> extends Parent<Self> {
    protected readonly m_child: SubChild<Self>;

    protected constructor(builder: new (p: Self) => SubChild<Self>) {
        super(builder as unknown as new (p: Self) => Child<Self>);
    }

    public static init() {
        return new SubParent(SubChild) as SubParent<SubParent<never>>;
    }

    /**
     * Sub parent actions
     */
}

Child 与 SubChild 类

export class Child<P extends Parent<P>> {
    private readonly m_parent: P;

    public constructor(parent: P) {
        this.m_parent = parent;
    }

    public get parent(): P {
        return this.m_parent;
    }

    /**
     * Child actions
     */
}

export class SubChild<P extends SubParent<P>> extends Child<P> {
    /**
     * Sub child actions
     */
}

关键改动说明

  1. 移除循环默认泛型:
    原代码中Parent<T extends Child = Child>和Child<T extends Parent = Parent>的默认值互相依赖,导致「Type parameter 'T' has a circular default」错误。现在改用递归泛型约束(Parent<Self extends Parent<Self>>),让类型通过自身引用建立约束,不再依赖默认值。

  2. 建立精准类型链条:

    • Parent的泛型参数Self表示自身类型,其child属性被约束为Child<Self>,确保子实例关联当前父实例的类型。
    • Child的泛型参数P表示对应的父类型,parent属性直接使用该类型,从根源上保证child.parent的类型与创建它的父实例一致。
  3. 子类类型传递:
    SubParent继承Parent时传递自身类型作为泛型参数,同时将child属性约束为SubChild<Self>;SubChild继承Child时约束父类型为SubParent<P>,确保子类的类型链条完全继承父类的类型关联。

  4. 静态方法类型断言:
    由于递归泛型无法完全自动推断,在init方法中使用类型断言明确实例类型,让TypeScript正确识别实例的具体类型。

验证类型正确性

const parent = Parent.init();           // 类型:Parent<Parent<never>>
const subParent = SubParent.init();     // 类型:SubParent<SubParent<never>>

const child = parent.child;             // 类型:Child<Parent<never>>
const subChild = subParent.child;       // 类型:SubChild<SubParent<never>>

const childParent = child.parent;       // 类型:Parent<Parent<never>>(即Parent类型)
const subChildParent = subChild.parent; // 类型:SubParent<SubParent<never>>(即SubParent类型)

此时TypeScript已能准确识别child.parent和subChild.parent的对应类型,且无需添加@ts-ignore规避错误。

内容的提问来源于stack exchange,提问作者Xavier Morell Llorens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:21:00