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

如何在TypeScript抽象类中实现返回子类构造参数的抽象方法?

TypeScript 抽象类 Entity 构造属性方法实现方案

需要在TypeScript中实现一个名为Entity的抽象类,其中包含一个抽象方法constructorProps(),该方法需返回子类构造所需的属性数组。

示例1:无自定义构造函数的子类

当子类没有自定义构造函数时,constructorProps()的返回类型应为空元组:

class Entity<Child extends Entity<any>> {
  abstract constructorProps(): // ??? 此处应填什么 ???
}

class Foo extends Entity<Foo> {
  override constructorProps() {
    return []
  }
}

示例2:带参数构造函数的子类

当子类实现了接收参数的构造函数时,constructorProps()需返回对应参数类型的数组,比如Bar类接收string类型参数,返回类型应为[string]:

class Bar extends Entity<Bar> {
  name: string;

  constructor(name: string) {
    super(); // 注意:子类自定义构造函数必须调用super()
    this.name = name;
  }
  
  override constructorProps() {
    return [this.name];
  }
}

思路与疑问

我已有初步思路——将子类作为类型参数传入抽象类,让Entity能够引用子类类型,但不清楚具体实现方式。

疑问:

  • 是否可以从实例类型(如ConstructorOf<Bar>)中获取构造函数的参数类型?
  • 当前的实现思路是否正确?有没有其他实现方式?

问题解答

疑问1:可以通过内置类型工具获取构造函数参数类型

TypeScript内置了ConstructorParameters工具类型,它能从构造函数类型中提取参数类型组成的元组。注意该工具接收的是构造函数类型而非实例类型,可通过typeof操作符从类本身获取构造函数类型:

// 从Bar类获取构造函数参数类型
type BarConstructorParams = ConstructorParameters<typeof Bar>; // 类型为 [string]

疑问2:你的思路可行,以下是具体实现方案

通过子类类型参数传递+ConstructorParameters工具类型,可自动约束constructorProps()的返回类型,无需手动指定。

完整实现代码

// 抽象类Entity,通过类型参数Child引用子类
abstract class Entity<Child extends Entity<any>> {
  // 利用ConstructorParameters自动推导子类构造函数的参数元组类型
  abstract constructorProps(): ConstructorParameters<typeof Child>;
}

// 无自定义构造函数的子类Foo
class Foo extends Entity<Foo> {
  override constructorProps() {
    return []; // 符合空元组类型要求
  }
}

// 带参数构造函数的子类Bar
class Bar extends Entity<Bar> {
  name: string;

  constructor(name: string) {
    super();
    this.name = name;
  }
  
  override constructorProps() {
    return [this.name]; // 符合[string]类型要求
  }
}

// 测试:返回类型不匹配时会触发TypeScript报错
class Baz extends Entity<Baz> {
  age: number;
  constructor(age: number, name: string) {
    super();
    this.age = age;
  }
  
  override constructorProps() {
    // 错误:类型 '[number]' 不能赋值给类型 '[number, string]'
    // return [this.age];
    return [this.age, "test"]; // 正确
  }
}

其他实现思路

如果不想通过子类类型参数传递,也可以直接用泛型约束指定构造参数元组,但这种方式需要子类手动声明参数类型,无法自动推导,实用性稍弱:

abstract class Entity<T extends any[] = []> {
  abstract constructorProps(): T;
}

class Foo extends Entity<[]> {
  override constructorProps() {
    return [];
  }
}

class Bar extends Entity<[string]> {
  name: string;
  constructor(name: string) {
    super();
    this.name = name;
  }
  override constructorProps() {
    return [this.name];
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:05:55