Interfaces, unions et narrowing
Décrire des objets avec interface et type, combiner des possibles avec les unions (|), et restreindre le type avec le narrowing.
Quand on ne peut plus se contenter de primitifs, on décrit des formes d'objets et on combine des possibles.
🧱 Interface ou type ?
Une interface est un contrat qui décrit la forme d'un objet (ses propriétés et leurs types). Elle peut être étendue (extends) et fusionnée (déclarée deux fois = fusion). Privilégiée pour les formes d'objets.
Un type est un alias qui peut décrire n'importe quoi : une union, une intersection, un tuple, un alias de primitive. Plus flexible que interface pour les combinaisons.
L'intersection (A & B) fusionne deux types en un seul. Le résultat a toutes les propriétés de A ET de B. Ex: User & { role: Role } = un User avec en plus un role.
| Outil | Usage privilégié |
|---|---|
interface | décrire des formes d'objets, extensible |
type | unions, intersections, aliases |
interface User {
id: number
nom: string
}
type Role = "admin" | "user" | "invite"
type UserAvecRole = User & { role: Role }🔀 Unions
L'union (A | B) est un type qui accepte aussi bien A que B. Une variable de type string | number peut contenir une chaîne OU un nombre. Le narrowing permet d'affiner.
Une union A | B accepte aussi bien A que B :
type Resultat =
| { ok: true; valeur: number }
| { ok: false; erreur: string }
const bon: Resultat = { ok: true, valeur: 42 }
const mauvais: Resultat = { ok: false, erreur: "échec" }🔍 Narrowing
Le narrowing (rétrécissement) est le processus par lequel TypeScript affine le type d'une variable dans une branche conditionnelle. Après if (typeof x === "string"), x est string dans la branche.
Une garde de type (type guard) est un test qui restreint le type. typeof, in, Array.isArray, instanceof sont des gardes built-in. Les fonctions v is T sont des gardes personnalisées.
Le narrowing restreint le type dans une branche :
function afficher(val: string | number) {
if (typeof val === "string") {
return val.toUpperCase() // ici val est string
}
return val.toFixed(2) // ici val est number
}Gardes disponibles
| Garde | Exemple |
|---|---|
typeof | typeof x === "string" |
in | "id" in obj |
Array.isArray | Array.isArray(x) |
function traiter(val: string | number[] | null) {
if (val === null) return "vide"
if (Array.isArray(val)) return val.length
return val.length // string
}Le littéral discriminé est une union dont chaque variante partage une propriété commune (souvent kind ou type). TypeScript utilise cette propriété pour automatiquement savoir dans quelle variante on se trouve.
📋 Points clés
- Interface : contrat pour les formes d'objets (extensible).
- Type : alias pour unions, intersections, combinaisons.
- Intersection (
&) : fusionne deux types. - Union (
|) : accepte plusieurs types possibles. - Narrowing : affine le type dans une branche conditionnelle.
- Garde : test qui restreint le type (
typeof,in,Array.isArray). - Littéral discriminé : propriété commune pour identifier automatiquement la variante.
📦 Enums
Un enum est un type qui nomme un ensemble de valeurs constantes. Les enums créent leur propre type et leurs propres valeurs au runtime. Utiles pour modéliser des choix fixes (statuts, rôles, directions).
Enum numérique (valeurs auto-incrémentées) :
enum Statut {
EnAttente, // 0
Valide, // 1
Refuse, // 2
}
const s: Statut = Statut.Valide // 1Enum string (valeurs explicites, plus lisibles) :
enum Couleur {
Rouge = "rouge",
Vert = "vert",
Bleu = "bleu",
}
const c: Couleur = Couleur.Rouge // "rouge"Préférence moderne : un as const + union de littéraux ("rouge" | "vert" | "bleu") est souvent plus léger et tree-shakable qu'un enum. Utilisez les enums quand vous avez besoin d'un objet runtime itérable ou de mappings bidirectionnels.
✅ Vérification des acquis
Quiz du chapitre
TypeScript
Terminez le quiz du chapitre pour le marquer comme complété.
Types primitifs et inférence
Découvrir les types de base de TypeScript (string, number, boolean, null, undefined) et comprendre comment l'inférence de types évite les annotations redondantes.
Génériques
Écrire du code réutilisable et typer avec les génériques : syntaxe <T>, contraintes extends, cas concrets (Result, ApiResponse).