TypeScript构造函数

Nir*_*rtz 4 typescript typescript1.8

我试图创建一个具有两个构造函数的类,并发现TypeScript不允许这样,但它允许重载构造函数,我试过它并得到一个错误:

构建:重载签名与功能实现不兼容.

我的代码:

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

我有两个问题,第一个问题,为什么我不能重载构造函数,我想我做错了什么.

但我的第二个问题,以及更多的交互是,我知道我的构造函数获取可选值.我可以(不使用方法中的代码!),在我的构造函数上创建一个条件,可以验证两个给定值中的一个必须存在,而在签名引导中是可选的,如下所示:

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

谢谢.

Joh*_*isz 9

在Typescript中,函数重载只不过是为单个函数体定义其他调用签名.并且由于只有一个函数体,所有过载签名必须与该初始函数声明兼容.参数的类型和值检查将手动完成.

在你的情况下,它有点棘手,因为接口定义在编译时丢失,因此你没有干净的方法来检查传递的参数是否是给定接口的实现.幸运的是,它是第一个参数的"对象或字符串"检查,第二个参数是"存在与否",因此检查接口是否已实现是不必要的:

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

这里,两个重载都与初始签名兼容.参数名称无关紧要,只有它们各自的类型和顺序(以及可选性).

TypeScript编译器知道typeofinstanceof检查,这导致您的变量被视为条件块内的正确类型.这被称为类型后卫.