2016-02-22 3 views
4

я попытался создать класс с двумя конструкторами и выяснить, что машинопись не позволяет, но это позволит перегрузки конструктора, а я попробовал его и получаю сообщение об ошибке:машинопись конструктор

Построить : Сигнатура перегрузки несовместима с реализацией функции.

Мой код:

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

У меня есть два вопроса, первый один, почему я не могу перегрузить конструктор, я предполагаю, что я делаю что-то неправильно.

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

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

Спасибо.

+1

Похоже, что это не связано с Angular2. Typecipt! = Angular2 –

+0

Opps, сделал это автоматически, не думая, я меняю его сейчас, извините. –

ответ

9

В машинописном виде перегрузка функций - это не что иное, как определение additional call signatures для одного тела функции. И поскольку существует только один объект функции, все сигнатуры перегрузки должны быть совместимы с этим объявлением начальной функции. Проверка типов и значений аргументов должна выполняться вручную.

В вашем случае это немного сложно, поскольку определения интерфейсов теряются при компиляции, поэтому у вас не будет чистого подхода, чтобы проверить, является ли переданный аргумент реализацией данного интерфейса. К счастью, это «объект или строка» проверить для первого параметра, и «существует или нет» для второго, поэтому проверка выполняется ли или нет интерфейса ненужно:

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

Здесь оба Перегрузок совместимый с начальной подписью. Имена параметров не имеют значения, только их соответствующие типы и порядок (а также необязательность).

Компилятор TypeScript знает о typeof и instanceof проверяет, что приводит к тому, что ваша переменная рассматривается как правильный тип внутри условного блока как таковой. Это называется type guard.

+0

Должны ли первые две строки 'constructor()' быть в интерфейсе? – Sasxa

+0

@Sasxa AFAIK, интерфейсы не могут определять сигнатуры конструкторов в TypeScript. ИМО, они не должны в любом случае, поскольку интерфейсы предназначены в первую очередь для определения использования, а не для создания.Для последнего, я бы сказал, это образец фабрики. –

+0

Спасибо за информацию. – Sasxa

3

Вы можете получить необходимую функциональность при статическом методе:

export class ShoppingListItem implements IShoppingListItem { 
    name: string; 
    amount: number; 

    constructor(item: IShoppingListItem) { 
     this.name = item.name; 
     this.amount = item.amount; 
    } 

    static create(name: string, amount: number) { 
     let item: IShoppingListItem = { name, amount }; 
     return new ShoppingListItem(item); 
    } 
} 

Вы можете создать ShoppingListItem так:

  • ShoppingListItem.create("Cat", 3)

  • ShoppingListItem({ name: "Cat", amount: 3 })