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

如何在TypeScript中创建使用泛型的父类构造函数,支持子类的对象初始化

如何在TypeScript中创建使用泛型的父类构造函数,支持子类的对象初始化

这个需求我之前也折腾过好几次,其实用TypeScript的泛型就能完美解决,既不用重复写构造函数,还能保留完整的类型提示,完全实现你想要的C#风格对象初始化效果。

核心思路是让基类通过泛型参数“捕获”子类的类型,这样构造函数里的Partial就能准确对应到子类的属性。话不多说,直接上可行的代码方案:

第一步:定义泛型基类

首先创建一个带泛型的基类,用泛型T来代表子类的类型,构造函数接收Partial<T>类型的初始化参数,然后用Object.assign把参数里的属性赋值给实例:

class Initializeable<T> {
  constructor(init?: Partial<T>) {
    Object.assign(this, init);
  }
}

第二步:子类继承并指定泛型参数

子类继承这个基类时,需要把泛型参数指定为自身类型,这样基类的构造函数就能正确识别子类的属性。另外注意用!非空断言标记属性,告诉TypeScript这些属性会被Object.assign初始化,避免编译器报错:

class Person extends Initializeable<Person> {
  firstName!: string;
  lastName!: string;
}

class Car extends Initializeable<Car> {
  make!: string;
  model!: string;
}

第三步:使用子类的初始化能力

现在你就可以像C#那样直接在new的时候传入初始化对象了,TypeScript会严格检查属性的类型和存在性,完全有类型提示:

const person = new Person({
  firstName: "Fred",
  lastName: "Flintstone"
});

const car = new Car({
  make: "Ford",
  model: "Model T"
});

扩展:子类自定义构造函数

如果子类需要自己的构造逻辑也不用担心,只要在子类构造函数里调用super(init),就能保留基类的初始化能力,同时添加自己的逻辑:

class Employee extends Initializeable<Employee> {
  firstName!: string;
  lastName!: string;
  employeeId!: number;

  constructor(init?: Partial<Employee>, employeeId?: number) {
    super(init);
    // 添加子类自己的构造逻辑
    if (employeeId) {
      this.employeeId = employeeId;
    }
  }
}

// 使用示例:可以混合传入初始化对象和自定义参数
const emp = new Employee({ firstName: "Barney" }, 123);

为什么之前的尝试没成功?

你提到的用Partial<this>或者Partial<typeof(this)不行,是因为在基类的构造函数里,this的类型是基类Initializeable本身,而不是子类。通过泛型显式指定子类类型,就能让TypeScript准确识别要初始化的属性集合。

这种方案既解决了代码冗余问题,又完全保留了TypeScript的类型安全特性,完美契合你的需求。

备注:内容来源于stack exchange,提问作者IsometricMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 14:19:34