TypeScript Constructor Overload with Empty Constructor

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

Why is it not allowed to have separate constructor definitions in TypeScript?
To have e.g. two constructors, I need to write my code like this.

constructor(id: number) constructor(id: number, name?: string, surname?: string, email?: string) {     this.id = id;     this.name = name;     this.surname = surname;     this.email = email; } 

Thereby I need to put ? after the things I want to be not required.

Why can't I write it like this?

constructor(id: number) {     this.id = id; }  constructor(id: number, name: string, surname: string, email: string) {     this.id = id;     this.name = name;     this.surname = surname;     this.email = email; } 

So that for each constructor all parameters are mandatory.

Moreover I need to have an empty constructor. This get even weirder, since I need to mark every parameter with a ?.

constructor() constructor(id?: number, name?: string, surname?: string, email?: string) {     this.id = id;     this.name = name;     this.surname = surname;     this.email = email; } 

Why does TypeScript differs from common languages like C# or Python here?

I would expect it to work like this.

constructor() {  } constructor(id: number, name: string, surname: string, email: string) {     this.id = id;     this.name = name;     this.surname = surname;     this.email = email; } 

So you can pass none parameter or must pass parameters.

回答1:

Because your constructor implementation is called by all your overload constructors. (Technically, at runtime there's only one constructor function that gets called with the various overload argument signatures.)

Imagine it like this:

overload_constructor(id:string) {     implementation_constructor(id); }  implementation_constructor(id:string, name?:string, age?:number) {     // ... } 

Thinking of it this way, overload_constructor could not call implementation_constructor unless name and age are optional.



回答2:

The last function overload is only used in the implementation and not available publicly. This is shown below:

class Foo{     constructor()     constructor(id?: number) {     } }  const foo1 = new Foo(); const foo2 = new Foo(123); // Error! : not public 

If you want id:number to be available publically ofcourse you can add another overload:

class Foo{     constructor()     constructor(id: number)     constructor(id?: number) {     } }  const foo1 = new Foo(); const foo2 = new Foo(123); // Okay const foo3 = new Foo('hello'); // Error: Does not match any public overload 

The reason is that TypeScript tries not to do fancy code generation for function overloading (traditional languages do this using name mangling e.g. C++)

So you can pass none parameter or must pass parameters.

Actually you can make the final overload optional but none of the public ones as optional. Consider the following example:

class Foo{       constructor(id: number, name:string)     constructor(name:string)     constructor(idOrName?: number|string, name?:string) {     } }  const foo1 = new Foo('name'); // Okay const foo2 = new Foo(123); // Error: you must provide a name if you use the id overload const foo3 = new Foo(123,'name'); // Okay 


回答3:

You can use Builder pattern to solve this. Even in C# or Python, it quickly becomes a better approach as the number of constructor arguments grows.

class Foo {   constructor(public id: number, public name: string, public surname: string, public email: string) {   }   static Builder = class {     id: number = NaN;     name: string = null;     surname: string = null;     email: string = null;     Builder() {     }     build(): Foo {       return new Foo(this.id, this.name, this.surname, this.email);     }   } } 


回答4:

If you use static methods to implement overload contructors, see.

export class User implements IUser {      constructor(         private _id: string,         private _name: string,         private _email: string,       ) {}     static New(jsonUser:string){         return new User(             JSON.parse(jsonUser).id,             JSON.parse(jsonUser).name,             JSON.parse(jsonUser).email)     } } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!