Конструктор перегрузки в машинописи

голоса
216

Кто-нибудь сделали конструктор перегружать в машинописи. На странице 64 спецификации языка (ст 0,8), есть утверждения, описывающие конструктор перегрузку, но не было никакого образец кода дан.

Я пытаюсь разработать действительно основную декларацию класса прямо сейчас; это выглядит так,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj: IBox) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   

    constructor() {
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
    }
}

Когда бежал с TSC BoxSample.ts, он выбрасывает повторяющееся определение конструктора - что очевидно. Любая помощь приветствуется.

Задан 03/10/2012 в 06:48
источник пользователем
На других языках...                            


13 ответов

голоса
190

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

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj?: IBox) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}

или два перегруженных с более общим конструктором, как в,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox); 
    constructor(obj?: any) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}
Ответил 03/10/2012 в 07:14
источник пользователем

голоса
63

Обратите внимание, что вы можете обойти отсутствие перегрузки на уровне реализации через параметры по умолчанию в машинописи, например:

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj : IBox = {x:0,y:0, height:0, width:0}) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   
}

Изменить: По состоянию на 5 декабря '16, см ответ Бенсона для более сложного решения , что позволяет более гибко.

Ответил 09/10/2012 в 07:29
источник пользователем

голоса
48

Что касается конструктора перегружает один альтернативы можно было бы реализовать дополнительные перегруженные как статические фабричные методы . Я думаю , что его более удобным для чтения и менее запутанным , чем тестирование ваших аргументов вызова. Вот простой пример:

class Person {
    static fromData(data: PersonData) {
        let { first, last, birthday, gender = 'M' } = data 
        return new this(
            `${last}, ${first}`,
            calculateAge(birthday),
            gender
        )
    }

    constructor(
        public fullName: string,
        public age: number,
        public gender: 'M' | 'F'
    ) {}
}

interface PersonData {
    first: string
    last: string
    birthday: string
    gender?: 'M' | 'F'
}


let personA = new Person('Doe, John', 31, 'M')
let personB = Person.fromData({
    first: 'John',
    last: 'Doe',
    birthday: '10-09-1986'
})

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

Ответил 31/07/2016 в 21:08
источник пользователем

голоса
38

Примечание: это было упрощено и обновлено 4/13/2017, чтобы отразить машинопись 2.1 см истории для машинописи 1.8 ответа.

Это звучит , как вы хотите, чтобы параметр объекта будет необязательным, а также каждого из свойств в объекте будет необязательным. В примере, как это предусмотрено, синтаксис перегрузки не требуется. Я хотел бы отметить некоторые плохие практики в некоторых из ответов здесь. Конечно, это не самое маленькое выражение по существу писать box = { x: 0, y: 87, width: 4, height: 0 }, но это дает все подсказки коды тонкости вы могли возможно хотеть от класса , как описано. Этот пример позволяет вызвать функцию с одним, некоторые, все, или ни один из параметров , и все еще получить значения по умолчанию.

 /** @class */
 class Box {
     public x?: number;
     public y?: number;
     public height?: number;
     public width?: number;     

     // The class can work double-duty as the interface here since they are identical
     // Alternately, reference your own interface, e.g.:  `...BoxI = {} as BoxI` 
     constructor(obj: Box = {} as Box) {

         // Define the properties of the incoming `obj` object here. 
         // Setting a default value with the `= 0` syntax is optional for each parameter
         let {
             x = 0,
             y = 0,
             height = 0,
             width = 0
         } = obj;

         /** Use jsdoc comments here for inline ide auto-documentation */
         this.x = x;
         this.y = y;
         this.height = height;
         this.width = width;
     }
 }

Это очень безопасный способ записи параметров, которые не могут иметь все свойства объекта, определенного. Теперь вы можете смело писать любого из них:

const box1 = new Box();
const box2 = new Box({});
const box3 = new Box({x:0});
const box4 = new Box({x:0, height:10});
const box5 = new Box({x:0, y:87,width:4,height:0});

 // Correctly reports error in TypeScript, and in js, box6.z is undefined
const box6 = new Box({z:0});  

Составитель, вы видите , что дополнительные параметры действительно являются необязательными, что позволяет избежать ловушек широко используется (но к ошибкам) запасной вариант синтаксиса var = isOptional || default;, проверяя против void 0, который является сокращением для undefined:

Составитель Выходной

var Box = (function () {
    function Box(obj) {
        if (obj === void 0) { obj = {}; }
        var _a = obj.x, 
        x = _a === void 0 ? 1 : _a,
        _b = obj.y,
        y = _b === void 0 ? 1 : _b,
        _c = obj.height,
        height = _c === void 0 ? 1 : _c,
        _d = obj.width,
        width = _d === void 0 ? 1 : _d;
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
    return Box;
}());

Приложение: Установка значений по умолчанию: неправильный путь

||(Или) оператора

Рассмотрим опасность ||/ или операторов при установке по умолчанию значения замещающего , как показано в некоторых других ответах. Этот код ниже иллюстрирует неправильный способ установки по умолчанию. Вы можете получить неожиданные результаты при оценке против falsey значений , как 0, «», NULL, неопределенный, ложный, NaN:

var myDesiredValue = 0;
var result = myDesiredValue || 2;

// This test will correctly report a problem with this setup.
console.assert(myDesiredValue === result && result === 0, 'Result should equal myDesiredValue. ' + myDesiredValue + ' does not equal ' + result);

Object.assign (это, OBJ)

В моих тестах, используя ES6 / машинопись деструктурированного объекта может быть почти 90% быстрее , чем Object.assign . Использование деструктурированного параметр позволяет только методы и свойства вы присвоенное объекту. Например, рассмотрим этот метод:

class BoxTest {
    public x?: number = 1;

    constructor(obj: BoxTest = {} as BoxTest) {
        Object.assign(this, obj);
    }
}

Если другой пользователь не использует машинопись и попытался поместить параметр , который не принадлежит, скажем, они могли бы попытаться положить zнедвижимость

var box = new BoxTest({x: 0, y: 87, width: 4, height: 0, z: 7});

// This test will correctly report an error with this setup. `z` was defined even though `z` is not an allowed property of obj.
console.assert(typeof box.z === 'undefined')
Ответил 05/12/2016 в 14:30
источник пользователем

голоса
32

Я знаю, что это старый вопрос, но новый в 1.4 типах профсоюзов; используйте их для всех функциональных перегрузок (в том числе и конструкторов). Пример:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);
Ответил 04/02/2015 в 18:28
источник пользователем

голоса
20

Обновление (8 июня 2017): guyarad и snolflake сделать действительные пункты в комментариях ниже мой ответ. Я бы рекомендовал читателям посмотреть на ответы по Бенсон , Джо и snolflake , которые имеют лучшие ответы , чем мои.

Ответ на языке оригинала (27 января 2014)

Другой пример того, как достичь конструктора перегрузки:

class DateHour {

  private date: Date;
  private relativeHour: number;

  constructor(year: number, month: number, day: number, relativeHour: number);
  constructor(date: Date, relativeHour: number);
  constructor(dateOrYear: any, monthOrRelativeHour: number, day?: number, relativeHour?: number) {
    if (typeof dateOrYear === "number") {
      this.date = new Date(dateOrYear, monthOrRelativeHour, day);
      this.relativeHour = relativeHour;
    } else {
      var date = <Date> dateOrYear;
      this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
      this.relativeHour = monthOrRelativeHour;
    }
  }
}

Источник: http://mimosite.com/blog/post/2013/04/08/Overloading-in-TypeScript

Ответил 27/01/2014 в 17:02
источник пользователем

голоса
3

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

export class Track {
   public title: string;
   public artist: string;
   public lyrics: string;

   constructor(track?: Track) {
     Object.assign(this, track);
   }
}

Имейте в виду , что это будет назначать все свойства , передаваемые в track, накануне , если они не определены на Track.

Ответил 06/11/2016 в 00:22
источник пользователем

голоса
1

Вы можете справиться с этим путем:

import { assign } from 'lodash'; // if you don't have lodash use Object.assign
class Box {
    x: number;
    y: number;
    height: number;
    width: number;
    constructor(obj: Partial<Box> = {}) {    
         assign(this, obj);
    }
}

Частичный сделают ваши поля (х, у, высота, ширина), что позволяет УСТРОЙСТВА нескольких конструкторов

например: вы можете сделать new Box({x,y})без высоты и ширины.

= {}Будет обрабатывать falsy значение , таких как неопределенный, нулевой и т.д., а затем вы можете сделатьnew Box()

Ответил 11/09/2018 в 09:36
источник пользователем

голоса
1

Другой вариант, как на @ ShinNoNoir код с использованием значений по умолчанию и синтаксиса распространения:

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor({x, y, height, width}: IBox = { x: 0, y: 0, height: 0, width: 0 }) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
}
Ответил 30/11/2016 в 05:11
источник пользователем

голоса
0

Я использую следующую альтернативу, чтобы получить по умолчанию / опциональный Params и «добрейший из перегруженного» Конструкторов с переменным числом Params:

private x?: number;
private y?: number;

constructor({x = 10, y}: {x?: number, y?: number}) {
 this.x = x;
 this.y = y;
}

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

Ответил 20/09/2019 в 14:28
источник пользователем

голоса
0

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

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox);
    constructor(obj?: IBox) {    
        this.x = !obj ? 0 : obj.x;
        this.y = !obj ? 0 : obj.y;
        this.height = !obj ? 0 : obj.height;
        this.width = !obj ? 0 : obj.width;
    }
}

поэтому вместо статических методов, которые вы можете сделать выше. Я надеюсь, что это поможет !!!

Ответил 26/05/2019 в 23:31
источник пользователем

голоса
0

Мы можем имитировать перегрузки конструктора с помощью охранников

interface IUser {
  name: string;
  lastName: string;
}

interface IUserRaw {
  UserName: string;
  UserLastName: string;
}

function isUserRaw(user): user is IUserRaw {
  return !!(user.UserName && user.UserLastName);
}

class User {
  name: string;
  lastName: string;

  constructor(data: IUser | IUserRaw) {
    if (isUserRaw(data)) {
      this.name = data.UserName;
      this.lastName = data.UserLastName;
    } else {
      this.name = data.name;
      this.lastName = data.lastName;
    }
  }
}

const user  = new User({ name: "Jhon", lastName: "Doe" })
const user2 = new User({ UserName: "Jhon", UserLastName: "Doe" })
Ответил 27/03/2019 в 00:18
источник пользователем

голоса
0

Вы должны имели в виду, что ...

застройщик ()

Конструктор (а: любой, Ь: любая, с: любая)

Это же из

Новый () или новый ( «а», «б», «в»)

таким образом

Конструктор (а: любой, Ь: любой, с: любой) таким же, выше и является более гибким ...

Новый () или новый ( «а») или новый ( «а», «б») или новый ( «а», «б», «в»)

Ответил 02/06/2018 в 14:15
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more