ProgrammationDéveloppeur Typescript

Parlez-moi du mécanisme de Declaration Merging dans TypeScript. Comment fonctionne-t-il pour les interfaces, les fonctions et les espaces de noms (namespace), et quels pièges existe-t-il ici ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Declaration Merging (fusion de déclarations) est un mécanisme unique de TypeScript qui permet de combiner des déclarations avec le même nom en un seul type/entité. Cela fonctionne pour les interfaces, les espaces de noms et les fonctions.

  1. Interfaces : les déclarations d'interface avec le même nom se fusionnent en une grande interface :
interface User { name: string; } interface User { age: number; } const u: User = { name: 'Vasya', age: 42 }; // OK
  1. Fonctions + namespace : une fonction et un espace de noms avec le même nom se fusionnent - les méthodes statiques sont agrégées :
function helper() {} namespace helper { export function extra() {} } helper.extra(); // OK
  1. Namespace + enum et namespace + class : la fusion est également possible pour l'extension de classes et d'enums avec des propriétés statiques.

Question piégeuse.

Comment se passe la fusion des méthodes avec des noms identiques dans différents espaces d'interface, et que se passe-t-il si leurs signatures diffèrent ?

Réponse :

Si vous déclarez dans différentes interfaces fusionnées des méthodes avec le même nom, TypeScript essaiera de "surcharger" ces méthodes dans l'interface finale. Cependant, si les signatures sont incompatibles (ne peuvent pas être surchargées), cela entraînera une erreur de compilation.

Exemple :

interface Foo { bar(a: number): void } interface Foo { bar(a: string): void } // OK : surcharges interface Foo { bar(a: number[]): void } // Erreur : signatures incompatibles

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Dans un projet, nous avons étendu l'interface Window tierce via la fusion de déclarations pour différentes fonctionnalités : une équipe a ajouté window.myFeature: boolean, l'autre window.myFeature: number. La fusion a causé une erreur de type, et le compilateur a détecté le conflit uniquement lors de l'assemblage général - quelqu'un a dû rapidement faire un renommage.


Histoire

Par erreur, deux interfaces ArrayHelper ont été déclarées avec des signatures de méthodes différentes, en s'attendant à ce qu'elles se combinent en "les deux variantes disponibles". En réalité, la première signature a écrasé la seconde, entraînant un autocomplétion incorrect dans l'IDE et un bug lors de l'intégration avec le nouveau module.


Histoire

En utilisant un espace de noms pour "étendre" une fonction via la fusion de déclarations, un développeur a mal déclaré l'exportation à l'intérieur de l'espace de noms, et la fonction s'est retrouvée inaccessible. Ce n'est qu'après une révision que nous avons réalisé qu'en l'absence d'une exportation correcte, la fusion ne fonctionnait pas et les propriétés n'apparaissaient pas sur la fonction.