Leçon 03 · Phase 0 — Socle TypeScript pour Angular · ~18 min

TypeScript #2 : décorateurs & async/Promise

Deux briques que tu croiseras dans chaque fichier Angular. Les décorateurs (@Component, @Injectable…) sont des cousins directs de tes attributs C#. Et l'asynchrone TypeScript (async/await/Promise) est quasi identique à ton Task. Encore une longueur d'avance.

Pourquoi ça compte pour Alliance Ouvre n'importe quel composant de leur ERP : la première ligne au-dessus de la classe sera un @Component({...}). Chaque service est un @Injectable(). Tu ne peux pas lire — encore moins revoir — du code Angular sans savoir ce que ces @ font réellement. Et dès que tu touches à un appel réseau, à un chargement de route ou à une initialisation, l'asynchrone débarque. Ces deux notions sont le ticket d'entrée.

1. Un décorateur, c'est quoi ?

Un décorateur est une annotation que tu colles juste au-dessus d'une classe, d'une propriété ou d'une méthode avec la syntaxe @quelqueChose(...). Il attache des métadonnées et/ou modifie l'élément décoré. Angular lit ces métadonnées pour comprendre « cette classe est un composant, voici son template, voici ses dépendances ».

Analogie .NET / C# C'est ton attribut C# : [HttpGet], [Authorize], [Serializable]. Tu décores une classe ou un membre, et un framework (ASP.NET, le sérialiseur…) lit l'info par réflexion pour adapter son comportement. Même position dans le code (au-dessus de l'élément), même but (« attacher une info que le framework va exploiter »). Une différence de fond plus bas — garde-la en tête.

2. Les décorateurs Angular que tu verras partout

Lis ce composant minimal. Chaque @ a un rôle précis :

import { Component, Input } from '@angular/core';

// @Component : « cette classe EST un composant ». Les métadonnées
// (sélecteur HTML, template) sont passées dans l'objet de config.
@Component({
  selector: 'app-poste',
  standalone: true,
  template: `<h3>{{ nom }}</h3>`,
})
export class PosteComponent {
  @Input() nom = '';   // @Input : ce champ est alimenté par le composant parent
}
DécorateurSur quoiCe qu'il dit à Angular
@Componentune classe« C'est un composant : voici son sélecteur et son template »
@Injectableune classe« Cette classe peut être injectée comme dépendance » (≈ service DI)
@Input()une propriété« Cette donnée vient du parent » (entrée du composant)
@Output()une propriété« Ce composant émet un événement vers le parent »
La différence de fond avec un attribut C# Un attribut C# est passif : c'est une étiquette inerte, qui ne fait rien tant qu'un code ne la lit pas par réflexion. Un décorateur TypeScript est une vraie fonction qui s'exécute : @Component({...}), c'est l'appel Component({...}) qui retourne une fonction appliquée à ta classe. Il peut donc modifier ce qu'il décore, pas seulement l'étiqueter. En pratique avec Angular tu t'en sers comme des attributs — mais sache que le mécanisme est actif, pas déclaratif.

3. L'asynchrone : Promise = Task

Une Promise<T> représente une valeur qui arrivera plus tard : un appel réseau, un fichier, un timer. C'est le clone de ton Task<T> C#. Et la cerise : async/await s'écrivent exactement pareil.

// Récupère un poste depuis une API. Promise<PosteMesure> ≈ Task<PosteMesure>
async function chargerPoste(id: number): Promise<PosteMesure> {
  const reponse = await fetch(`/api/postes/${id}`); // await, comme en C#
  if (!reponse.ok) {
    throw new Error('Poste introuvable');          // throw classique
  }
  return reponse.json();                              // la valeur résolue de la Promise
}

// Appel : on await dans une autre fonction async, et on try/catch les erreurs
try {
  const poste = await chargerPoste(1);
} catch (e) {
  // gestion d'erreur, comme un catch sur un await Task
}
TypeScriptÉquivalent C#Note
Promise<T>Task<T>Une valeur future typée
async / awaitasync / awaitIdentique au mot près
.then(cb)ContinueWith / awaitL'ancienne façon, avant await
.catch(cb) / try/catchtry/catchMême logique d'erreur
Promise.all([a, b])Task.WhenAll(a, b)Attendre plusieurs en parallèle
Œil de tech lead Deux pièges classiques que tu signaleras en revue. (1) Oublier le await : tu manipules alors la Promise elle-même (l'« enveloppe ») au lieu de sa valeur — exactement comme oublier d'await une Task en C#. (2) Lancer en série ce qui pourrait être parallèle : deux await à la suite alors qu'un Promise.all ferait les deux en même temps.

4. Nuance importante pour Angular : Promise vs Observable

Tu viens de voir fetch + Promise, et c'est juste du TypeScript standard. Mais sache-le dès maintenant : pour les appels réseau, Angular privilégie les Observable (RxJS), pas les Promise. La différence en une phrase : une Promise livre une seule valeur, une fois ; un Observable est un flux qui peut en livrer zéro, une ou plusieurs, et qu'on peut annuler. On y consacrera des leçons entières (RxJS, phase 1). Les Promise restent bien présentes ailleurs : chargement de routes, import() dynamique, initialisation d'app. Donc tu dois maîtriser les deux.

5. Vérifie ta compréhension

Quel est le rôle de @Component({...}) au-dessus d'une classe ?
En C#, Task<T> correspond en TypeScript à…
Tu écris const poste = chargerPoste(1); sans await (la fonction renvoie une Promise). Que contient poste ?
À retenir Un décorateur @X(...) attache des métadonnées à une classe/propriété (≈ attribut C#, mais c'est une fonction active). Les incontournables : @Component, @Injectable, @Input(), @Output(). Côté asynchrone, Promise<T> = Task<T> et async/await sont identiques à C# ; Promise.all = Task.WhenAll. Piège : un await oublié te laisse l'enveloppe. À venir : Angular préfère les Observable (RxJS) aux Promise pour le réseau.
Source primaire à lire (10 min)

MDN — Comment utiliser les promesses (en français). Lis l'intro, « then() et la gestion d'erreur », et « async et await ». C'est la base universelle, indépendante d'Angular.

Je suis ton prof — pose-moi des questions. Tu veux voir comment Angular utilise réellement les métadonnées d'un décorateur en coulisses, ou pourquoi l'équipe choisit un Observable plutôt qu'une Promise sur tel appel ? Demande-moi, ici, maintenant.
◀ 02 · TypeScript #1 : types & interfaces Suivant : 04 · Data binding dans le template ▶