ProgrammationDéveloppeur Fullstack

Comment fonctionne l'extension des types (extends), quels sont les nuances d'utilisation avec les types et les interfaces, et comment cela influence-t-il la structure de votre projet ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En TypeScript, il est possible d'étendre (hériter) des types à la fois avec interface extends et avec type & type (types d'intersection). Les interfaces peuvent également étendre des types, et vice versa.

Interfaces utilisent le mot-clé extends pour hériter des propriétés :

interface Animal { name: string; } interface Bird extends Animal { wings: number; }

Types peuvent être combinés via & :

type Animal = { name: string }; type Bird = Animal & { wings: number };

De plus, une interface peut étendre un autre type :

type Base = { id: number }; interface Derived extends Base { description: string; }

Particularités :

  • Les interfaces supportent la fusion déclarative (declaration merging), les types — non.
  • Les interfaces sont recommandées si l'on s'attend à étendre d'autres entités (par exemple, pour des bibliothèques).
  • Les extends imbriqués peuvent entraîner une hiérarchie complexe, compliquer la maintenance et créer des conflits de noms.

Question piégée

Peut-on étendre un type (type) à travers une interface ou vice versa ? Quelle erreur commet la plupart des gens ?

Beaucoup pensent qu'il n'est possible d'étendre que des interfaces à travers des interfaces, mais en réalité, une interface peut étendre un type :

type Basic = { flag: boolean }; interface Extra extends Basic { name: string; }

Cependant, un type ne peut pas être étendu via extends par d'autres types — uniquement par intersection de types (&).

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un grand projet, ils combinaient des interfaces par extends, oubliant que les propriétés portant le même nom devaient correspondre par type. Lorsque quelqu'un a modifié le type d'une propriété dans l'interface parente, des conflits silencieux ont surgi dans les enfants, et la base a cessé de correspondre à l'API.

Histoire

Dans la bibliothèque, ils ont écrit des type-aliases avec des propriétés chevauchantes via & (intersections), mais certaines propriétés ont été rendues incompatibles par type. TypeScript a ignoré cela au moment de la compilation, mais en réalité, des champs indéfinis sont apparus au moment de l'exécution du système.

Histoire

L'équipe croyait qu'une interface ne pouvait pas être étendue par un type, et pour étendre la fonctionnalité commune, ils réécrivaient toutes les structures de type en interface, dépensant beaucoup de temps et d'efforts — alors qu'il aurait simplement été possible d'étendre les types existants de manière non conventionnelle.