ProgrammationDéveloppeur Typescript

Comment fonctionne la typage des fonctions avec surcharge (overload) en TypeScript, et quelle est sa différence par rapport à la surcharge des méthodes dans d'autres langages ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

Dans des langages comme Java ou C#, la surcharge des fonctions et des méthodes est une fonctionnalité standard : il est possible de déclarer plusieurs fonctions avec le même nom mais avec des paramètres différents. En JavaScript, cela n'existe pas, ce qui ajoute des erreurs potentielles. TypeScript résout ce problème au niveau des types.

Problème

En TypeScript, il n'y a pas de véritable surcharge (multiple réalisations). On peut déclarer plusieurs signatures d'une même fonction, mais implémenter une seule fonction. Les erreurs surviennent lors de la désynchronisation des signatures déclarées et de l'implémentation, ou lors d'un mauvais positionnement des signatures.

Solution

TypeScript prend en charge la surcharge des fonctions en déclarant plusieurs signatures consécutivement et une unique réalisation réelle, compatible avec toutes les variantes de surcharge.

Exemple de code :

function sum(a: number, b: number): number; function sum(a: string, b: string): string; function sum(a: any, b: any): any { return a + b; } const a = sum(1, 2); // 3 const b = sum('foo', 'bar'); // "foobar"

Caractéristiques clés :

  • Toujours une seule réalisation après toutes les signatures
  • L'implémentation doit être compatible avec toutes les variantes de surcharge
  • TypeScript vérifie la validité des appels lors de l'utilisation de la fonction surchargée

Questions piégées.

Peut-on définir l'implémentation d'une fonction avant de déclarer toutes les signatures de surcharge ?

Non, toutes les signatures de surcharge doivent être déclarées d'abord, puis l'implémentation. Erreur :

// Erreur ! D'abord les signatures, ensuite l'implémentation function foo(a: number): number { return a } // erreur function foo(a: string): string { return a } // erreur

TypeScript vérifie-t-il les valeurs de retour dans toutes les signatures de surcharge ?

TypeScript garantit le retour de types conformément aux signatures déclarées uniquement au moment de la compilation ; aucune vérification de types n'a lieu à l'exécution.

Est-il obligatoire de couvrir toutes les variantes d'entrée dans une seule réalisation ?

La fonction-implémentation doit traiter correctement toutes les variantes d'entrée selon les signatures de surcharge :

function parse(a: number): string; function parse(a: string): string; function parse(a: number | string): string { return String(a); }

Erreurs typiques et anti-patterns

  • Désalignement entre la réalisation et les signatures de surcharge
  • Mauvaise ordre de déclaration des signatures et de l'implémentation
  • Traitement/ignorance implicite des combinaisons de types

Exemple de la vie réelle

Cas négatif

Plusieurs surcharges de la fonction avec différents types d'entrées sont déclarées, mais l'implémentation ne traite pas tous les cas et lance une erreur à l'exécution lors d'entrées rares.

Avantages :

  • API flexible pour les utilisateurs de la fonction

Inconvénients :

  • Les types se compilent, mais le fonctionnement de la fonction est incorrect sans vérifications supplémentaires dans le corps

Cas positif

Chaque surcharge de fonction est couverte par une condition sur les types dans la réalisation, des vérifications de type (typeof/instanceof) sont utilisées.

Avantages :

  • API sûre et prévisible
  • Les erreurs sont détectées au moment de la compilation

Inconvénients :

  • Augmente la base de code en raison des vérifications supplémentaires