如何在TypeScript中的派生类中进行构造函数重载?

Lee*_*e H 8 inheritance constructor extends overloading typescript

假设我有一个'基础'类,如下所示:

class CcDefinition {
  // Some properties here

  constructor (json: string);
  constructor (someVar: number, someOtherVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      // some JSON wrangling code here
    } else {
      // assign someVar and someOtherVar to the properties
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够扩展这个基类,同时仍然支持构造函数重载.例如:

class CcDerived extends CcDefinition {
  // Some additional properties here

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      super.constructFromJson(jsonOrSomeVar);
    } else {
      super.constructFromDef(someOtherVar, someAdditionalVar);
      // assign someVar to the additional properties of this derived class
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是Typescript要求'super'关键字在构造函数实现中首先出现(字面上).特定的生成错误消息是:

"当一个类包含初始化属性或具有参数属性时,''超级'调用必须是构造函数中的第一个语句."

但是,我需要根据提供给扩展(派生)类的内容确定将传递给'super'的哪些参数(即使用不同的构造函数重载).你应该假设派生类的构造函数重载可能与超类有很大的不同.

对于我想要实现的目标,是否有解决方法?

Rya*_*ugh 7

此限制仅适用于在派生类中初始化成员属性的情况,因此第一种解决方法是仅声明这些属性,然后在派生类构造函数中初始化它们.

换句话说,你可以改变:

class CcDerived extends CcDefinition {
  y = 10;

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      super(jsonOrSomeVar);
    } else {
      super(someOtherVar, someAdditionalVar);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

对此:

class CcDerived extends CcDefinition {
  // Some additional properties here
  y: number;

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    this.y = 10;
    if (typeof jsonOrSomeVar=== "string") {
      super(jsonOrSomeVar);
    } else {
      super(someOtherVar, someAdditionalVar);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此处的初始化顺序与其他OOP语言大致相同,您需要注意不要从构造函数等调用虚方法.

如果这太令人反感,请注意限制只是第一个语句是超级调用.你经常可以重构超级电话:

class CcDerived extends CcDefinition {
  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
      super(
          typeof jsonOrSomeVar === 'string' ? jsonOrSomeVar : someOtherVar,
          typeof jsonOrSomeVar === 'string' ? undefined : someAdditionalVar); 
  }
}
Run Code Online (Sandbox Code Playgroud)

不是最漂亮的,但它至少在语义上是等价的.这假设您的基类构造函数正在检查undefined(而不是arguments.length)以确定调用了哪个重载.