为什么不允许在 TypeScript 中使用单独的 constructor
定义?
要有例如两个 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;
}
所以你可以传递无参数或必须传递所有参数。
答案 0 :(得分:25)
最后一个函数重载仅用于实现,不公开。如下所示:
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尝试不为函数重载执行花哨的代码生成(传统语言使用名称修改来执行此操作,例如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
答案 1 :(得分:20)
因为所有重载构造函数都调用了构造函数实现。 (从技术上讲,在运行时,只有一个构造函数可以使用各种重载参数签名进行调用。)
想象一下:
overload_constructor(id:string) {
implementation_constructor(id);
}
implementation_constructor(id:string, name?:string, age?:number) {
// ...
}
以这种方式思考,overload_constructor
无法调用implementation_constructor
,除非name
和age
是可选的。
另见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;
}
请注意,在实现中,所有参数都是可选的,但编译时不会公开该签名,您只能使用这些调用:
new Foo()
new Foo(1)
new Foo(1, "a", "b", "c")
不是,例如:
new Foo(1, "a")
答案 2 :(得分:0)
您可以使用Builder模式来解决此问题。即使在C#或Python中,随着构造函数参数数量的增加,它也会迅速成为一种更好的方法。
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);
}
}
}
答案 3 :(得分:-1)
如果使用静态方法实现过载构造函数,请参阅。
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)
}
}