Décorateurs et metadata
Enrichissement déclaratif et table de routage automatique.
Objectifs
À la fin de cette leçon, vous saurez :
- expliquer ce qu'un décorateur ajoute à une classe ou une méthode ;
- comprendre la reflection : lire des informations sur son propre code ;
- démystifier @Controller() de NestJS.
🔗 Pour vous rafraîchir la mémoire : les bases TypeScript · anatomie d'une requête HTTP · méthodes HTTP et codes de statut
Le décorateur : une annotation qui agit
function journaliser(cible: any, nom: string, desc: PropertyDescriptor) {
const original = desc.value;
desc.value = function (...args) {
console.log(`Appel ${nom}(${args.join(", ")})`);
return original.apply(this, args);
};
}
class Service {
@journaliser
calculer(a: number) { return a * 2; }
}
new Service().calculer(21);
// "Appel calculer(21)" puis 42
Un décorateur est une fonction préfixée @ qui reçoit la définition décorée (classe, méthode, propriété) et peut l'enrichir. Ici : envelopper la méthode avec un log — sans toucher à son corps.
Les cibles possibles
@decorateur class MaClasse → la classe entière
@decorateur methode() → une méthode
@decorateur propriete → un champ
@parametre constructeur(x: string) → un paramètre
NestJS utilisera massivement classes et méthodes ; les paramètres serviront aux @Body(), @Param() que vous avez déjà croisés dans le code de Devmind.
La reflection : lire ses propres définitions
La reflection est la capacité d'un programme à s'inspecter :
Reflect.getMetadata("role", MaClasse); // lire ce qui y a été attaché
Le duo qui fait tourner NestJS :
- Écriture au chargement : les décorateurs attachent des métadonnées.
- Lecture au démarrage : le framework parcourt les classes et construit ses tables.
Démystifier @Controller("/users")
Ce que fait conceptuellement le décorateur de route :
@Controller("/users") ← écrit dans la classe :
classe UserController metadata "prefix" = "/users"
@Get(":id") metadata "route GET /:id" → méthode findOne
findOne(id) {}
au démarrage, Nest lit ces métadonnées :
GET /users/:id → UserController.findOne ← la table de routage !
Rien de magique : c'est votre routeur regex du chapitre 19, dont les règles ont été collectées automatiquement depuis les décorateurs plutôt que déclarées à la main.
Exercice
- Écrivez @Chronometrer qui logge la durée de chaque appel de méthode.
- Écrivez un décorateur de classe qui logge son instanciation.
- Décrivez en pseudo-code comment Nest associerait POST /tasks à TasksController.creer.
Résumé
- Décorateur = enrichissement déclaratif d'une définition.
- Metadata + reflection = le framework lit vos annotations au boot.
- @Get/@Controller = votre table de routage écrite autrement.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 3. Au chargement du module TasksController : @Controller("tasks") attache prefix=tasks ; @Post() sur creer attache method=POST path=/ sur cette méthode. Au boot, Nest parcourt chaque contrôleur enregistré, combine prefix+path, enregistre {POST /tasks → creer} dans sa table, puis chaque requête consulte cette table — exactement votre boucle for sur routes[] du chapitre 19.