How can I do constructor overloading in a derived class in TypeScript?

Assuming I have a base class such as:

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 } } } 

I want to be able to extend this base class while maintaining constructor overload. For example:

 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 } } } 

The problem is that Typescript requires the 'super' keyword to be displayed first (literally) in the constructor implementation. Specific build error message:

The "super" call must be the first statement in the constructor when the class contains initialized properties or has parameter properties. "

However, I need to determine which parameters I will go into "super" (that is, use the overload of another constructor) based on what was provided to the extended (derived) class. Here you must assume that the constructor overloads of the derived class can be very different from super.

Is there a way I'm trying to achieve?

+7
inheritance constructor overloading extends typescript
source share
1 answer

This restriction only applies if you initialized the properties of an element in a derived class, so the first workaround is to simply declare these properties and then initialize them in the constructor of the derived class.

In other words, you can change:

 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); } } } 

:

 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); } } } 

Please note that the initialization order here is approximately the same as in other OOP languages, and you need to be careful not to call virtual methods from constructors, etc.

If this is too annoying, note that the limitation is simply that the first statement is a super call. You can often reorganize a super call:

 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); } } 

Not the most beautiful, but it is at least semantically equivalent. This assumes your base class constructor checks undefined (instead of arguments.length ) to determine which overload has been called.

+7
source share

All Articles