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

如何在TypeScript中构建返回值类型精确的mixin工厂函数

你遇到的报错是因为原有实现对泛型的约束和返回值类型不匹配:当输入参数是抽象构造器时,写死的返回值ConcreteConstructor无法兼容抽象类的类型定义,同时TypeScript无法直接推导匿名子类和泛型T的交叉类型关系。

可行实现方案

// 定义两种构造器类型,兼容普通类和抽象类
type ConcreteConstructor<T = {}> = new (...args: any[]) => T;
type AbstractConstructor<T = {}> = abstract new (...args: any[]) => T;
type AnyConstructor<T = {}> = ConcreteConstructor<T> | AbstractConstructor<T>;

function Unique<T extends AnyConstructor>(BaseClass: T) {
  // 扩展传入的基类
  const ExtendedClass = class extends BaseClass {
    public readonly uniqueId = Symbol();
  };

  // 通过条件类型自动推导返回值类型,适配普通类/抽象类两种输入
  return ExtendedClass as T extends ConcreteConstructor<infer Instance>
    ? ConcreteConstructor<Instance & { readonly uniqueId: symbol }>
    : T extends AbstractConstructor<infer Instance>
    ? AbstractConstructor<Instance & { readonly uniqueId: symbol }>
    : never;
}

验证效果

无需任何类型断言,即可同时识别基类成员和新增的uniqueId属性:

// 测试普通类
class Dog {
  constructor(public name: string) {}
  bark() {
    return "汪";
  }
}
const UniqueDog = Unique(Dog);
const myDog = new UniqueDog("大黄");
// 可正常调用 myDog.name、myDog.bark()、myDog.uniqueId,类型推导全部正确

// 测试抽象类
abstract class Animal {
  abstract move(): void;
  age = 0;
}
const UniqueAnimal = Unique(Animal);
// 符合抽象类特性:无法直接 new UniqueAnimal()
class Bird extends UniqueAnimal {
  move() {
    console.log("飞");
  }
}
const myBird = new Bird();
// 可正常调用 myBird.age、myBird.move()、myBird.uniqueId,类型推导全部正确

该实现完全满足需求:支持扩展任意普通类/抽象类,返回值类型自动保留基类所有类型信息,同时新增uniqueId属性的类型定义,无需额外类型断言。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 07:51:03