TypeScript constructor

I tried to create a class with two constructors and find out that TypeScript does not allow this, but it allows you to overload the constructor, well, I tried this and got an error:

Build: overload signature is incompatible with the implementation of the function.

My code is:

interface IShoppingListItem { name: string; amount: number; } export class ShoppingListItem implements IShoppingListItem{ name: string; amount: number; constructor(item: IShoppingListItem); constructor(name: string, amount: number) { this.name = name; this.amount = amount; } copy() { //return new this.constructor(this); } } 

I have two questions: firstly, why I can not overload the constructor, I think I'm doing something wrong.

But my second question and more interaction, I know, I am a constructor that gets additional values. Can I (not with the code inside the method!) Create a condition for my constructor, which can verify that one of the two given values ​​should exist, while loading the signature is optional, for example:

 constructor(item?: IShoppingListItem, name?: string, amount?: number) { //make a condition that item or name and amount must exist this.name = name; this.amount = amount; } 

Thanks.

+4
typescript
source share
2 answers

In Typescript, function overloading is nothing more than defining additional signature signatures for one function body. And since there is only one function body, all overload signatures must be compatible with this initial function declaration . Checking parameters and argument values ​​is done manually.

In your case, this is a little complicated, because the definitions of the interfaces are lost during compilation, so you will not have a clean approach to check if the passed argument is an implementation of this interface. Fortunately, this “object or string” checks your first parameter and “exists or not” for the second, so checking if the interface is implemented is not required:

 export class ShoppingListItem implements IShoppingListItem { // 2 overload signatures from which you can choose on the invocation side constructor(item: IShoppingListItem); constructor(name: string, amount: number); // the function declaration itself, compatible with both of the above overloads // (in VS, IntelliSense will not offer this version for autocompletion) constructor(nameOrItem: string | IShoppingListItem, amount?: number) { if (typeof nameOrItem === "object") { // the first argument is an object, due to overload signature, // it is safe to assume it is of type IShoppingListItem // ... } else if (typeof nameOrItem === "string" && typeof amount === "number") { this.name = nameOrItem; this.amount = amount; } } } 

Here, both overloads are compatible with the original signature. Parameter names do not matter, only their respective types and order (as well as optional).

The TypeScript compiler is aware of typeof and instanceof checks, which means that your variable is treated as the correct type inside the conditional block as such. This is called type protection.

+9
source share

You can get the necessary functionality with a static method:

 export class ShoppingListItem implements IShoppingListItem { name: string; amount: number; constructor(item: IShoppingListItem) { this.name = item.name; this.amount = item.amount; } static create(name: string, amount: number) { let item: IShoppingListItem = { name, amount }; return new ShoppingListItem(item); } } 

You can create ShoppingListItem as follows:

  • ShoppingListItem.create("Cat", 3)

  • ShoppingListItem({ name: "Cat", amount: 3 })

+3
source share

All Articles