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

如何避免JavaScript类按引用传递问题,同时保留TypeScript泛型类型

报错原因

你定义的泛型EffectInstance extends Effect允许传入Effect的任意子类型,你手动判断仅覆盖了Effect和PlayerEffect两种类型,TS无法确认这两种类型能匹配所有可能的EffectInstance子类型,因此抛出类型不兼容错误。

解决方案

方案1:为基类新增clone方法(最推荐)

在Effect基类定义克隆方法,所有子类自行重写实现自己的克隆逻辑,既保证类型完全匹配,也不用在构造函数里判断类型:

class Effect {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  clone(): this {
    return new Effect(this.name) as this;
  }
}

class PlayerEffect extends Effect {
  ignoreRaces: string[];
  constructor(name: string, ignoreRaces: string[]) {
    super(name);
    this.ignoreRaces = ignoreRaces;
  }
  clone(): this {
    return new PlayerEffect(this.name, [...this.ignoreRaces]) as this;
  }
}

构造函数直接调用克隆方法即可:

constructor(effect: EffectInstance, names: string[], count?: number) {
    this.effect = effect;
    const altEffect = effect.clone();
    for (const name of names) {
        this.custom.set(name, altEffect);
    }
}

方案2:添加类型断言(适合无法修改基类的场景)

如果你确认已经覆盖了所有EffectInstance的子类型,可以直接添加类型断言绕过TS校验:

constructor(effect: EffectInstance, names: string[], count?: number) {
    this.effect = effect;
    let altEffect: EffectInstance;
    if (effect instanceof PlayerEffect) {
        altEffect = new PlayerEffect(effect.name, effect.ignoreRaces) as EffectInstance;
    } else {
        altEffect = new Effect(effect.name) as EffectInstance;
    }
    for (const name of names) {
        this.custom.set(name, altEffect);
    }
}

注意不要用JSON.parse(JSON.stringify())这类通用深拷贝方法,会丢失类的原型方法,导致实例类型异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:57:01