Existe-t-il un moyen d'ajouter des méthodes à la volée à une classe à l'aide de TypeScript ?
-
12-12-2019 - |
Question
J'essaie de créer une sorte de méthode mixin qui ajoute des méthodes au prototype/classe à la volée mais j'obtiens des erreurs telles que
La propriété «saluer» n'existe pas sur la valeur du type «greeter»
et
La propriété «saluer» n'existe pas sur la valeur du type «greeter»
quand j'exécute le code suivant.
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'));
Il se compile en fait en js valide et s'exécute comme prévu.Existe-t-il un moyen de le faire sans avertissements/erreurs du compilateur ?
La solution
Cette solution a l'avantage de vous donner le type de vérification lorsque vous ajoutez de manière dynamique une méthode:
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();
Autres conseils
Ils auraient besoin d'un concept de classes partielles pour que cela fonctionne, ce qui ne soit actuellement pas pris en charge.Je vous dirai que ce que j'ai trouvé mieux fonctionne mieux pour ces types de scénarios consiste à utiliser des interfaces à la place (je suis programmée dans TypeScript pendant environ 6 mois maintenant - je suis chez moi mais pas sur l'équipe TypeScript)
Les interfaces sont extensibles après le fait de définir simplement les méthodes que vous ajoutez à l'interface.À titre d'exemple, si vous installez un plugin JQuery, vous souhaitez ré-définir l'interface IJQUERY & IJQUERYUTIL pour inclure les méthodes supplémentaires des plug-ins.À partir de ce point, vous pouvez appeler les méthodes de plug-ins via $ .plugin () et TypeScript sera heureux.
Il y a une autre façon de le faire.
Greeter["SomeProperty"] = function() {
return "somevalue";
};
fonctionne la même chose et utilise la fonction d'indexateur de propriété dans JavaScript et Typescript ne se plaint pas.
Semblable à l'exemple de @fenton, mais sans les trucs gnarly:
class MyClass {
start() {
}
}
MyClass.prototype['stop'] = function () {
alert('Stop');
}
interface MyClass {
stop(): void;
}
var example = new MyClass();
example.stop(); // Allowed!!!
C'est ainsi RxJS
est-ce que c'est
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) {
}
C’est ce qu’on appelle l’augmentation de module.
Après avoir à mettre en œuvre des méthodes et des propriétés dynamiques sur les classes, c'était la solution que j'ai pu utiliser pour empêcher le compilateur dossier de se plaindre:
...
window.alert(greeter['greetName']('Name'));
Fondamentalement, utilisez la méthode du support de Accessoires de propriété .