Les décorateurs sont des annotations spéciales qui permettent de modifier le comportement des classes, propriétés, méthodes ou paramètres en utilisant des méta-informations supplémentaires ou en remplaçant l'implémentation.
Ils sont généralement utilisés pour l'injection de dépendances, la journalisation, la validation, la mise en cache ou la déclaration de métadonnées pour des frameworks comme Angular.
Exemple d'un simple décorateur de méthode :
function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const original = descriptor.value; descriptor.value = function(...args: any[]) { console.log(`Call: ${propertyKey}(${JSON.stringify(args)})`); return original.apply(this, args); }; } class Example { @Log doSomething(a: number, b: number) { return a + b; } }
Pièges :
experimentalDecorators est activé dans tsconfig.Question : "Peut-on typer les paramètres du décorateur de manière à garantir le type de la méthode à laquelle il est appliqué ?"
Réponse : Dans la plupart des cas, le typage est impossible au moment de l'application du décorateur en raison de la nature dynamique de la méta-programmation. Cependant, via des génériques et des vérifications supplémentaires à l'exécution, on peut ajouter une validation, mais le compilateur TypeScript ne garantira pas au moment de la déclaration de la structure.
Exemple :
function MyDecorator(target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<number>) { /* ... */ } // Le compilateur ne garantit pas que la méthode retourne un number
Histoire
Dans un projet avec de nombreux décorateurs sur des services, on a oublié l'ordre d'application : les décorateurs de propriété ont été appliqués avant tous les paramètres, ce qui a entraîné la perte des métadonnées Inject et l'incapacité de résoudre les dépendances à l'exécution.
Histoire
Les développeurs ont décidé d'appliquer des décorateurs à des fonctions normales plutôt qu'à des méthodes de classe, et ont été surpris par les erreurs de compilation et l'absence d'effet à l'exécution. Dans la spécification TypeScript, les décorateurs ne peuvent être appliqués qu'aux classes et à leurs membres.
Histoire
Après la mise à jour des versions de TypeScript et des paramètres expérimentaux, tout le mécanisme des décorateurs dans un conteneur DI personnalisé s'est effondré : il s'est avéré que la nouvelle version nécessite un support explicite de Reflect-metadata, sinon toutes les méta-informations étaient perdues.