Types, interfaces et génériques
Unions, literals, interface/type, génériques utiles.
Objectifs
À la fin de cette leçon, vous saurez :
- utiliser les types primitifs, tableaux, unions et literals ;
- décrire des formes avec type et interface ;
- écrire un premier générique utile.
Les types de base
let titre: string = "Courses";
let fois: number = 3;
let fait: boolean = false;
let ids: number[] = [1, 2, 3];
let paire: [string, number] = ["Ana", 21]; // tuple : longueur + ordre fixés
Unions : l'un ou l'autre
type Statut = "brouillon" | "publie" | "archive"; // literal union
function afficherStatut(s: Statut) { ... }
afficherStatut("publie"); // ✅
afficherStatut("oublie"); // ❌ refusé à la compilation
let id: string | number; // les deux acceptés, mais seulement les opérations communes
Les literal unions remplacent avantageusement des chaînes magiques dispersées : le compilateur connaît TOUTES les valeurs légales. C'est exactement votre enum de statuts (DRAFT/PUBLISHED/ARCHIVED) devenu inviolable.
Décrire une forme : type et interface
interface Utilisateur {
id: number;
nom: string;
email?: string; // optionnel
readonly creeLe: Date; // non modifiable après création
}
const u: Utilisateur = { id: 1, nom: "Ana", creeLe: new Date() };
u.email = "a@x.fr"; // ✅ champ optionnel renseigné
interface et type se recoupent largement ; convention pratique du cours : interface pour les formes d'objets (extensible), type pour unions et alias composés.
type TacheIncomplete = Partial<Utilisateur>; // tout devient optionnel
type Resume = Pick<Utilisateur, "id" | "nom">; // sous-ensemble
Les génériques : réutiliser la forme
function premier<T>(liste: T[]): T | undefined {
return liste[0];
}
premier([1, 2, 3]); // number | undefined
premier(["a", "b"]); // string | undefined — sans perdre le type !
<T> est un paramètre de type : la fonction garde la LIAISON entre entrée et sortie. Sans lui, il faudrait choisir entre any[] (aucune sécurité) et une copie par type.
Cas d'usage immédiat dans votre projet :
interface ReponseApi<T> {
statut: "ok" | "erreur";
donnees?: T;
}
const r: ReponseApi<Utilisateur> = ...;
Exercice
- Modelez Tache (id, titre, fait, creeLe) puis StatutTache en literal union.
- Écrivez
basculer(t: Tache): Tachequi renvoie une NOUVELLE tâche (immuable). - Généralisez en
basculerChamp<K extends keyof T>? Non — plus simple : écrivezResultat<T>avec ok(valeur) / erreur(motif). - Pourquoi
email?: stringdiffère-t-il deemail: string | undefined?
Résumé
- Unions + literals = domaines de valeurs fermés vérifiés.
- interface/type = contrats documentés et vérifiés.
- Génériques = liaisons de types réutilisables sans any.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 2.
function basculer(t: Tache): Tache {
return { ...t, fait: !t.fait };
}
Question 4. email?: string signifie « la propriété peut NE PAS EXISTER » ; email: string | undefined exige que la clé soit présente même avec undefined. Avec exactOptionalPropertyTypes, TS traite cette différence explicitement — subtilité qui compte aux frontières JSON.