TypeScript Перегрузка конструктора с пустым конструктором

Почему не разрешено иметь отдельные определения constructor в TypeScript? Чтобы иметь, например, два constructors, мне нужно написать свой код следующим образом.

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

Таким образом, мне нужно поместить ? после того, что я не хочу требовать.

Почему я не могу написать это так?

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

Так что для каждого конструктора все параметры обязательны.

Кроме того, мне нужно иметь пустой конструктор. Это становится еще более странным, так как мне нужно отметить каждый параметр с помощью ?.

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

Почему TypeScript отличается от обычных языков, таких как C# или Python здесь?

Я ожидаю, что он будет работать следующим образом.

constructor() {

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

Таким образом, вы не можете передавать ни один параметр или не передавать параметры.

Ответы

Ответ 1

Потому что ваша реализация конструктора вызывается всеми вашими конструкторами перегрузки. (Технически во время выполнения есть только одна функция-конструктор, которая вызывается с различными сигналами аргументов перегрузки.)

Представьте себе это так:

overload_constructor(id:string) {
    implementation_constructor(id);
}

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

Подумав об этом, overload_constructor не смог вызвать implementation_constructor, если name и age не являются обязательными.

Ответ 2

Последняя функция перегрузки используется только в реализации и недоступна публично. Это показано ниже:

class Foo{
    constructor()
    constructor(id?: number) {
    }
}

const foo1 = new Foo();
const foo2 = new Foo(123); // Error! : not public

Если вы хотите, чтобы id:number был доступен публично, вы можете добавить еще одну перегрузку:

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

Причина заключается в том, что TypeScript пытается не создавать генерации фэнтези-кода для перегрузки функций (традиционные языки делают это с помощью манипуляции с именем, например С++)

Таким образом, вы не можете передавать ни один параметр или не передавать параметры.

На самом деле вы можете сделать окончательную перегрузку опциональной, но ни одна из публичных не является обязательной. Рассмотрим следующий пример:

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

Если вы используете статические методы для реализации конструкторов перегрузки, см.

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