Introduction : le débat éternel des développeurs TypeScript
Si vous avez déjà écrit en TypeScript, vous vous êtes sûrement posé la question : « Quand utiliser interface et quand utiliser type ? » Cette question a rassemblé des milliers de vues sur Stack Overflow et est devenue une véritable pierre d'achoppement pour les débutants. Mettons fin une fois pour toutes à ce dilemme.
TypeScript est une surcouche de JavaScript qui ajoute un typage statique. Nous avons deux outils principaux pour décrire la structure des données : Interface et Type Alias. À première vue, ils font la même chose, mais le diable se cache dans les détails. Dans cet article, nous ne nous contenterons pas d'énumérer les différences — nous les montrerons avec des exemples concrets et donnerons des recommandations claires.
Qu'est-ce qu'une Interface ?
Une Interface est une façon de décrire la structure d'un objet. C'est comme un plan pour les données : vous dites à TypeScript quelles propriétés et méthodes un objet doit avoir.
// Interface de baseinterface User { name: string; age: number; email?: string; // propriété facultative readonly id: number; // lecture seule}
// Utilisationconst user: User = { name: "Anna", age: 25, id: 1};Les interfaces peuvent hériter les unes des autres, ce qui les rend idéales pour décrire des hiérarchies :
interface Animal { name: string; sound(): void;}
interface Dog extends Animal { breed: string; wagTail(): void;}
// Désormais, Dog contient tous les champs d'Animal + les siensconst myDog: Dog = { name: "Rex", breed: "Berger", sound() { console.log("Ouaf !"); }, wagTail() { console.log("Remue la queue"); }};Qu'est-ce qu'un Type Alias ?
Un Type Alias (alias de type) est un outil plus flexible. Il peut décrire non seulement des objets, mais aussi des primitives, des unions et des intersections de types.
// Type pour une primitivetype ID = string | number;
// Type pour un objettype UserType = { name: string; age: number;};
// Type pour une fonctiontype Greeting = (name: string) => string;
// Union Typetype Status = "active" | "inactive" | "pending";
// Intersection Typetype Person = { name: string };type Employee = Person & { salary: number };Le super-pouvoir principal des types, ce sont les union types. Les interfaces ne savent pas faire cela :
// ❌ Impossible avec interface// interface Status = "active" | "inactive"; // Erreur !
// ✅ Avec type, c'est facile !type Status = "active" | "inactive" | "pending";
function processStatus(status: Status) { switch (status) { case "active": console.log("Actif"); break; case "inactive": console.log("Inactif"); break; case "pending": console.log("En attente"); break; }}Différences clés : Interface vs Type
Détaillons leurs différences pratiques.
1. Union et intersection de types
Type supporte directement l'union (|) et l'intersection (&). Interface, uniquement via extends.
// Union — seulement avec typetype Success = { data: string };type Error = { error: string };type Result = Success | Error; // Possible !
// Intersectiontype Full = Success & Error; // Possible !
// Avec interface, il faudrait créer des interfaces séparéesinterface IResult extends Success, Error {} // Fonctionne, mais lourd2. Declaration merging (fusion de déclarations)
C'est une fonctionnalité unique des interfaces. Si vous déclarez deux interfaces avec le même nom, TypeScript les fusionne.
// Première interfaceinterface User { name: string;}
// Deuxième interface avec le même nominterface User { age: number;}
// Résultat : User = { name: string; age: number; }const user: User = {