使用空构造函数的TypeScript构造函数重载

Dan*_*zel 36 constructor typescript

为什么不允许constructorTypeScript中使用单独的定义?
要有两个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;
}
Run Code Online (Sandbox Code Playgroud)

因此,我需要?在第一个构造函数中不需要的参数之后.

为什么我不能这样写呢?

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;
}
Run Code Online (Sandbox Code Playgroud)

因此,对于两个构造函数,所有参数都是必需的.

而且,如果我需要一个空的构造函数,事情变得更加怪异,因为我需要用a标记每个参数?.

constructor()
constructor(id?: number, name?: string, surname?: string, email?: string) {
    this.id = id;
    this.name = name;
    this.surname = surname;
    this.email = email;
}
Run Code Online (Sandbox Code Playgroud)

为什么打字稿从像普通语言不同,C#或者Python在这里?

我希望它能像这样工作.

constructor() {

}
constructor(id: number, name: string, surname: string, email: string) {
    this.id = id;
    this.name = name;
    this.surname = surname;
    this.email = email;
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以传递无参数或必须传递所有参数.

bas*_*rat 27

最后一个函数重载仅用于实现,不公开.如下所示:

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

const foo1 = new Foo();
const foo2 = new Foo(123); // Error! : not public
Run Code Online (Sandbox Code Playgroud)

如果您希望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
Run Code Online (Sandbox Code Playgroud)

原因是TypeScript尝试不为函数重载执行花哨的代码生成(传统语言使用名称修改来执行此操作,例如C++)

所以你可以传递无参数或必须传递参数.

实际上你可以使最终的重载是可选的,但是没有公共的重载是可选的.请考虑以下示例:

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
Run Code Online (Sandbox Code Playgroud)


Aar*_*all 23

因为您的构造函数实现由所有重载构造函数调用.(从技术上讲,在运行时只有一个构造函数可以使用各种重载参数签名进行调用.)

想象一下这样:

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

implementation_constructor(id:string, name?:string, age?:number) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

以这种方式思考,除非并且是可选的,overload_constructor否则不能打电话.implementation_constructornameage

另请参阅Basarat的答案,类型检查器不会公开实现该实现(尽管在运行时它是JS中使用的"真正的"构造函数).如果您只想允许(),(id)(id, name, surname, email)作为唯一有效的呼叫签名,您可以这样做:

constructor()
constructor(id: number)
constructor(id: number, name: string, surname: string, email: string)
constructor(id?: number, name?: string, surname?: string, email?: string) {
    this.id = id;
    this.name = name;
    this.surname = surname;
    this.email = email;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在实现中,所有参数都是可选的,但编译时不会公开该签名,您只能使用这些调用:

new Foo()
new Foo(1)
new Foo(1, "a", "b", "c")
Run Code Online (Sandbox Code Playgroud)

不是,例如:

new Foo(1, "a")
Run Code Online (Sandbox Code Playgroud)