Pergunta

Existe uma maneira de sobrecarregar métodos na linguagem TypeScript?

Eu quero conseguir algo assim:

class TestClass {
    someMethod(stringParameter: string): void {
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    someMethod(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }
}

var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");

Aqui está um exemplo do que eu não quero fazer (eu realmente odeio essa parte de sobrecarregar hack em JS):

class TestClass {
    private someMethod_Overload_string(stringParameter: string): void {
        // A lot of code could be here... I don't want to mix it with switch or if statement in general function
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    private someMethod_Overload_number_string(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }

    private someMethod_Overload_string_number(stringParameter: string, numberParameter: number): void {
        alert("Variant #3: stringParameter = " + stringParameter + ", numberParameter = " + numberParameter);
    }

    public someMethod(stringParameter: string): void;
    public someMethod(numberParameter: number, stringParameter: string): void;
    public someMethod(stringParameter: string, numberParameter: number): void;

    public someMethod(): void {
        switch (arguments.length) {
        case 1:
            if(typeof arguments[0] == "string") {
                this.someMethod_Overload_string(arguments[0]);
                return;
            }
            return; // Unreachable area for this case, unnecessary return statement
        case 2:
            if ((typeof arguments[0] == "number") &&
                (typeof arguments[1] == "string")) {
                this.someMethod_Overload_number_string(arguments[0], arguments[1]);
            }
            else if ((typeof arguments[0] == "string") &&
                     (typeof arguments[1] == "number")) {
                this.someMethod_Overload_string_number(arguments[0], arguments[1]);
            }
            return; // Unreachable area for this case, unnecessary return statement
        }
    }
}


var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");
testClass.someMethod("string for v#3", 54321);
Foi útil?

Solução

De acordo com a especificação, o TypeScript suporta sobrecarga de métodos, mas é bastante estranho e inclui muito trabalho manual para verificar tipos de parâmetros.Acho que é principalmente porque o mais próximo que você pode chegar da sobrecarga de métodos em JavaScript simples inclui essa verificação também e o TypeScript tenta não modificar os corpos reais dos métodos para evitar qualquer custo desnecessário de desempenho em tempo de execução.

Se bem entendi, você deve primeiro escrever uma declaração de método para cada uma das sobrecargas e depois um implementação de método que verifica seus argumentos para decidir qual sobrecarga foi chamada.A assinatura da implementação deve ser compatível com todas as sobrecargas.

class TestClass {
    someMethod(stringParameter: string): void;
    someMethod(numberParameter: number, stringParameter: string): void;

    someMethod(stringOrNumberParameter: any, stringParameter?: string): void {
        if (stringOrNumberParameter && typeof stringOrNumberParameter == "number")
            alert("Variant #2: numberParameter = " + stringOrNumberParameter + ", stringParameter = " + stringParameter);
        else
            alert("Variant #1: stringParameter = " + stringOrNumberParameter);
    }
}

Outras dicas

Atualização para maior clareza.A sobrecarga de métodos no TypeScript é um recurso útil na medida em que permite criar definições de tipo para bibliotecas existentes com uma API que precisa ser representada.

Porém, ao escrever seu próprio código, você poderá evitar a sobrecarga cognitiva de sobrecargas usando parâmetros opcionais ou padrão.Esta é a alternativa mais legível para sobrecargas de métodos e também mantém sua API honesta, pois evitará a criação de sobrecargas com pedidos não intuitivos.

A lei geral das sobrecargas do TypeScript é:

Se você puder excluir as assinaturas de sobrecarga e todos os seus testes passarem, você não precisará de sobrecargas TypeScript

Geralmente você pode conseguir a mesma coisa com parâmetros opcionais ou padrão - ou com tipos de união, ou com um pouco de orientação a objetos.

A questão real

A questão real pede uma sobrecarga de:

someMethod(stringParameter: string): void {

someMethod(numberParameter: number, stringParameter: string): void {

Agora, mesmo em linguagens que suportam sobrecargas com implementações separadas (nota:Sobrecargas TypeScript compartilham uma única implementação) - os programadores são aconselhados a fornecer consistência na ordenação.Isso faria com que as assinaturas:

someMethod(stringParameter: string): void {

someMethod(stringParameter: string, numberParameter: number): void {

O stringParameter é sempre necessário, então vai primeiro.Você poderia escrever isso como uma sobrecarga de TypeScript funcional:

someMethod(stringParameter: string): void;
someMethod(stringParameter: string, numberParameter: number): void;
someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}

Mas seguindo a lei das sobrecargas do TypeScript, podemos excluir as assinaturas de sobrecarga e todos os nossos testes ainda serão aprovados.

someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}

A questão real, na ordem real

Se você estivesse determinado a persistir com o pedido original, as sobrecargas seriam:

someMethod(stringParameter: string): void;
someMethod(numberParameter: number, stringParameter: string): void;
someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}

Agora é muita ramificação para descobrir onde colocar os parâmetros, mas você realmente queria preservar essa ordem se estiver lendo até aqui...mas espere, o que acontece se aplicarmos a lei das sobrecargas do TypeScript?

someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}

Já chega de ramificação

Claro, dada a quantidade de verificação de tipo que precisamos fazer...talvez a melhor resposta seja simplesmente ter dois métodos:

someMethod(stringParameter: string): void {
  this.someOtherMethod(0, stringParameter);
}

someOtherMethod(numberParameter: number, stringParameter: string): void {
  //...
}

Eu desejo.Eu também quero esse recurso, mas o TypeScript precisa ser interoperável com JavaScript não digitado, que não possui métodos sobrecarregados.ou sejaSe o seu método sobrecarregado for chamado a partir de JavaScript, ele só poderá ser despachado para uma implementação de método.

Existem algumas discussões relevantes sobre codeplex.por exemplo.

https://typescript.codeplex.com/workitem/617

Ainda acho que o TypeScript deveria gerar todos os if'ing e switching para que não precisassemos fazer isso.

Por que não usar interface definida por propriedade opcional como o argumento da função.

Para o caso desta questão, usar uma interface embutida definida apenas com algumas propriedades opcionais poderia criar diretamente um código como algo abaixo:

class TestClass {

    someMethod(arg: { stringParameter: string, numberParameter?: number }): void {
        let numberParameterMsg = "Variant #1:";
        if (arg.numberParameter) {
            numberParameterMsg = `Variant #2: numberParameter = ${arg.numberParameter},`;
        }
        alert(`${numberParameterMsg} stringParameter = ${arg.stringParameter}`);
    }
}

var testClass = new TestClass();
testClass.someMethod({ stringParameter: "string for v#1" });
testClass.someMethod({ numberParameter: 12345, stringParameter: "string for v#2" });

Porque a sobrecarga fornecida no TypeScript é, como mencionado nos comentários de outros, apenas uma lista de diferentes assinaturas de funções sem suporte a códigos de implementação correspondentes, como outras linguagens estáticas.Portanto, a implementação ainda precisa ser feita em apenas um corpo de função, o que torna o uso da sobrecarga de funções no Typescript não tão confortável quanto as linguagens que suportam o recurso de sobrecarga real.

No entanto, ainda há muitos itens novos e convenientes fornecidos em TypeScript que não estão disponíveis na linguagem de programação legada, onde o suporte opcional de propriedades em uma interface anônima é uma abordagem para atender à zona confortável da sobrecarga de funções legadas, eu acho.

Javascript não tem nenhum conceito de sobrecarga.Typescript não é c# ou Java.

Mas você pode implementar a sobrecarga no Typescript.

Leia esta postagemhttp://www.gyanparkash.in/function-overloading-in-typescript/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top