with - typescript specification




Sobrecarga de construtor no TypeScript (7)

Alguém fez sobrecarga de construtor no TypeScript. Na página 64 da especificação de linguagem (v 0.8), há instruções descrevendo sobrecargas de construtor, mas não foi fornecido nenhum código de amostra.

Eu estou tentando uma declaração de classe realmente básica agora; Se parece com isso,

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

Quando executado com o tsc BoxSample.ts, ele lança uma definição de construtor duplicada - o que é óbvio. Qualquer ajuda é apreciada.


Em relação às sobrecargas do construtor, uma alternativa seria implementar as sobrecargas adicionais como métodos estáticos de fábrica . Eu acho que é mais legível e menos confuso do que testar seus argumentos de chamada. Aqui está um exemplo simples:

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

A sobrecarga de método no TypeScript não é real , digamos, porque exigiria muito código gerado pelo compilador e a equipe principal tentaria evitar isso a todo custo. Atualmente, o motivo principal para a sobrecarga de método estar presente na linguagem é fornecer uma maneira de gravar declarações para bibliotecas com argumentos mágicos em sua API. Como você precisará fazer todo o trabalho pesado sozinho para lidar com diferentes conjuntos de argumentos, não vejo muita vantagem em usar sobrecargas em vez de métodos separados.


Eu sei que esta é uma questão antiga, mas novo em 1.4 é tipos de união; use-os para todas as sobrecargas de função (incluindo construtores). Exemplo:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);

O TypeScript permite que você declare sobrecargas, mas você só pode ter uma implementação e essa implementação deve ter uma assinatura que seja compatível com todas as sobrecargas. No seu exemplo, isso pode ser feito facilmente com um parâmetro opcional, como em

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

ou duas sobrecargas com um construtor mais geral como em,

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

Observe que você também pode contornar a falta de sobrecarga no nível de implementação por meio de parâmetros padrão no TypeScript, por exemplo:

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

Edit: A partir de 05 de dezembro '16, veja a resposta de Benson para uma solução mais elaborada que permite mais flexibilidade.


Você deveria ter em mente que ...

contructor()

constructor(a:any, b:any, c:any)

É o mesmo que new() ou new("a","b","c")

portanto

constructor(a?:any, b?:any, c?:any)

é o mesmo acima e é mais flexível ...

new() ou new("a") ou new("a","b") ou new("a","b","c")


Você pode lidar com isso:

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

Parcial tornará seus campos (x, y, altura, largura) opcionais, permitindo vários construtores

ex .: você pode fazer o new Box({x,y}) sem altura e largura.

O = {} irá manipular falsy valor como undefined, null etc, e então você pode fazer new Box()


Atualização (8 de junho de 2017): guyarad e snolflake fazem pontos válidos em seus comentários abaixo da minha resposta. Eu recomendaria aos leitores que olhassem as respostas de Benson , Joe e snolflake que têm melhores respostas do que as minhas.

Resposta original (27 de janeiro de 2014)

Outro exemplo de como conseguir a sobrecarga do construtor:

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

Fonte: http://mimosite.com/blog/post/2013/04/08/Overloading-in-TypeScript







overloading