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

TypeScript有界多态方案中泛型T的非any默认值设置方法

二叉搜索树(BST)与统计二叉搜索树的三种TypeScript实现方案

我尝试为二叉搜索树(BST)以及带有额外size属性的统计二叉搜索树建模,试验了三种实现方案:

  • 递归方案
  • 多态方案
  • 有界多态方案

1. 递归方案

递归方案对子类支持不佳,每个基类方法都需要在子类中重写以匹配子类类型。

// 1. 递归方案
interface IBSTRec<K, V> {
    key: K;
    value: V;
    left?: IBSTRec<K, V>;
    right?: IBSTRec<K, V>;
}

class BSTRec<K, V> implements IBSTRec<K, V> {
    constructor(
        public key: K, 
        public value: V, 
        public left?: BSTRec<K, V>, 
        public right?: BSTRec<K, V>
    ) { /* ... */ }

    insert(node: BSTRec<K, V>): BSTRec<K, V> {
        // Insert logic...
        return node;
    }
}

interface IStatisticBSTRec<K, V> extends BSTRec<K, V> {
    size: number;
}

class StatisticBSTRec<K, V> extends BSTRec<K, V> {
    size = 1;

    constructor(key: K, value: V, left?: StatisticBSTRec<K, V>, right?: StatisticBSTRec<K, V>) {
        super(key, value, left, right);
        this.size += (left?.size || 0) + (right?.size || 0);
    }

    insert(node: StatisticBSTRec<K, V>): StatisticBSTRec<K, V> {
        const inserted = super.insert(node);
        // Update size for inserted node's ancestors...
        return inserted as StatisticBSTRec<K, V>;
    }
}

2. 多态方案

多态方案表现良好,子类无需进行类型断言即可适配基类方法。

// 2. 多态方案
interface IBSTPoly<K, V> {
    key: K;
    value: V;
    left?: this;
    right?: this;
}

class BSTPoly<K, V> implements IBSTPoly<K, V> {
    key: K;
    value: V;
    left?: this;
    right?: this;
    constructor(key: K, value: V, left?: BSTPoly<K, V>, right?: BSTPoly<K, V>) {
         this.key = key;
         this.value = value;
         if (left) this.left = left as this;
         if (right) this.right = right as this;
    }

    insert(node: this): this {
        // Insert logic...
        return this;
    }
}

interface IStatisticBSTPoly<K, V> extends IBSTPoly<K, V> {
    size: number;
}

class StatisticBSTPoly<K, V> extends BSTPoly<K, V> implements IStatisticBSTPoly<K, V> {
    size = 1;

    constructor(key: K, value: V, left?: StatisticBSTPoly<K, V>, right?: StatisticBSTPoly<K, V>) {
        super(key, value, left, right);
        this.size += (left?.size || 0) + (right?.size || 0);
    }

    insert(node: this): this {
        const inserted = super.insert(node);
        // Update size for inserted node's ancestors...
        return inserted;
    }
}

3. 有界多态方案(待解决问题)

在探索用TypeScript泛型约束描述节点递归关系的有界多态方案时,遇到无法将泛型参数T自身作为默认值的问题,当前只能用any填充默认值。需要解决:如何在不使用any的情况下为T设置正确的默认值?

// 3. 有界多态方案
interface IBSTBoRec<K, V, T extends IBSTBoRec<K, V, T> = IBSTBoRec<K, V, any>> {
    key: K;
    value: V;
    left?: T;
    right?: T;
}

// Can't use T for its own default, so using any.
class BSTBoRec<K, V, T extends IBSTBoRec<K, V, T> = BSTBoRec<K, V, any>> implements IBSTBoRec<K, V, T> {
    constructor(
        public key: K, 
        public value: V, 
        public left?: T, 
        public right?: T
    ) { /* ... */ }

    insert(node: T): T {
        // Insert logic...
        return node;
    }
}

interface IStatisticBSTBoRec<K, V, T extends IStatisticBSTBoRec<K, V, T> = IStatisticBSTBoRec<K, V, any>> 
        extends IBSTBoRec<K, V, T> {
    size: number;
}

class StatisticBSTBoRec<K, V, T extends StatisticBSTBoRec<K, V, T> = StatisticBSTBoRec<K, V, any>> 
        extends BSTBoRec<K, V, T> implements IStatisticBSTBoRec<K, V, T> {
    size = 1;

    constructor(key: K, value: V, left?: T, right?: T) {
        super(key, value, left, right);
        this.size += (left?.size || 0) + (right?.size || 0);
    }

    insert(node: T): T {
        const inserted = super.insert(node);
        // Update size for inserted node's ancestors...
        return inserted;
    }
}

解决方案:使用自引用默认类型

TypeScript不允许直接将泛型参数自身作为默认值,但可以通过定义自引用的基础类型替代any,保证类型安全。

步骤1:定义默认自引用BST节点类型

// 定义默认的自引用BST节点类型
class DefaultBSTBoRec<K, V> implements IBSTBoRec<K, V, DefaultBSTBoRec<K, V>> {
    constructor(
        public key: K,
        public value: V,
        public left?: DefaultBSTBoRec<K, V>,
        public right?: DefaultBSTBoRec<K, V>
    ) {}

    insert(node: DefaultBSTBoRec<K, V>): DefaultBSTBoRec<K, V> {
        // 实现默认插入逻辑
        return node;
    }
}

步骤2:修改泛型默认值

将接口和类的泛型默认值从any替换为上述自引用类型:

interface IBSTBoRec<K, V, T extends IBSTBoRec<K, V, T> = DefaultBSTBoRec<K, V>> {
    key: K;
    value: V;
    left?: T;
    right?: T;
    insert(node: T): T;
}

class BSTBoRec<K, V, T extends IBSTBoRec<K, V, T> = DefaultBSTBoRec<K, V>> implements IBSTBoRec<K, V, T> {
    constructor(
        public key: K, 
        public value: V, 
        public left?: T, 
        public right?: T
    ) { /* ... */ }

    insert(node: T): T {
        // Insert logic...
        return node;
    }
}

步骤3:为统计二叉搜索树适配默认类型

// 定义默认的自引用统计BST节点类型
class DefaultStatisticBSTBoRec<K, V> extends BSTBoRec<K, V, DefaultStatisticBSTBoRec<K, V>> implements IStatisticBSTBoRec<K, V, DefaultStatisticBSTBoRec<K, V>> {
    size = 1;

    constructor(key: K, value: V, left?: DefaultStatisticBSTBoRec<K, V>, right?: DefaultStatisticBSTBoRec<K, V>) {
        super(key, value, left, right);
        this.size += (left?.size || 0) + (right?.size || 0);
    }

    insert(node: DefaultStatisticBSTBoRec<K, V>): DefaultStatisticBSTBoRec<K, V> {
        const inserted = super.insert(node);
        // 更新size逻辑
        return inserted;
    }
}

// 修改统计BST的泛型默认值
interface IStatisticBSTBoRec<K, V, T extends IStatisticBSTBoRec<K, V, T> = DefaultStatisticBSTBoRec<K, V>> 
        extends IBSTBoRec<K, V, T> {
    size: number;
}

class StatisticBSTBoRec<K, V, T extends StatisticBSTBoRec<K, V, T> = DefaultStatisticBSTBoRec<K, V>> 
        extends BSTBoRec<K, V, T> implements IStatisticBSTBoRec<K, V, T> {
    size = 1;

    constructor(key: K, value: V, left?: T, right?: T) {
        super(key, value, left, right);
        this.size += (left?.size || 0) + (right?.size || 0);
    }

    insert(node: T): T {
        const inserted = super.insert(node);
        // Update size for inserted node's ancestors...
        return inserted;
    }
}

核心思路

通过定义具体的自引用默认类型,既满足泛型约束的递归要求,又避免any带来的类型不安全问题。当未显式指定泛型参数T时,自动使用该默认类型,保证类型检查的严谨性。


内容的提问来源于stack exchange,提问作者Robert Kajic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:25:54