Existe uma maneira de adicionar métodos dinamicamente a uma classe usando TypeScript?

StackOverflow https://stackoverflow.com//questions/12698893

  •  12-12-2019
  •  | 
  •  

Pergunta

Estou tentando criar algum tipo de método mixin que adicione métodos ao protótipo/classe instantaneamente, mas recebo erros como

A propriedade 'GreetName' não existe no valor do tipo 'cumprimentador'

e

A propriedade 'GreetName' não existe no valor do tipo 'cumprimentador'

quando executo o código a seguir.

class Greeter {
    greeting: string;
    constructor (message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

Greeter.prototype.greetName = function(name){
        return this.greet() + ' ' + name;
}

var greeter = new Greeter('Mr');

window.alert(greeter.greetName('Name'));

Na verdade, ele compila para js válido e é executado conforme o esperado.Existe uma maneira de fazer isso sem avisos/erros do compilador?

Foi útil?

Solução

Esta solução tem a vantagem de fornecer verificação de tipo quando você adiciona um método dinamicamente:

class MyClass {
    start() {

    }
}
var example = new MyClass();
// example.stop(); not allowed


interface MyClass {
  stop(): void;
}

MyClass.prototype['stop'] = function () {
    alert('Stop');
}
var stage2 = example;
stage2.stop();

Outras dicas

Eles precisariam de um conceito de classes parciais para que isso funcionasse, o que atualmente não é suportado.Vou lhe dizer que o que descobri que funciona melhor para esses tipos de cenários é usar interfaces (estou programando em TypeScript há cerca de 6 meses - estou na MS, mas não na equipe TypeScript)

As interfaces são extensíveis simplesmente definindo os métodos que você está adicionando à interface.Como exemplo disso, se você instalar um plug-in jQuery, você desejará redefinir a interface IJQuery e IJQueryUtil para incluir métodos adicionais do plug-in.Desse ponto em diante, você pode invocar os métodos dos plugins através de $.plugin() e o TypeScript ficará feliz.

Existe outra maneira de fazer isso.

Greeter["SomeProperty"] = function() {
     return "somevalue";
};

Funciona da mesma forma e usa a função indexadora de propriedades em javascript e o typescript não reclama.

Semelhante ao exemplo do @Fenton, mas sem as coisas complicadas:

class MyClass {
    start() {
    }
}
MyClass.prototype['stop'] = function () {
    alert('Stop');
}

interface MyClass {
    stop(): void;
}

var example = new MyClass();
example.stop(); // Allowed!!!

É assim RxJS faz isso

import {Observable} from "./observable"; // which is Greeter in your case 


declare module "./observable" {
    interface Observable<T> {
        map<U>(f: (x: T) => U): Observable<U>;
    }
}

Observable.prototype.map = function (f) {

}

Isso é chamado de Aumento de Módulo.

Depois de implementar métodos e propriedades dinâmicas nas classes, esta foi a solução que consegui para evitar que o compilador Typescript reclamasse:

...
window.alert(greeter['greetName']('Name'));

Basicamente, use o método de colchetes de acessadores de propriedade.

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