Historique de la question:
TypeScript prend en charge la surcharge des méthodes, comme d'autres langages à typage strict (par exemple, Java ou C#), cependant la syntaxe de surcharge en TypeScript diffère conceptuellement. Ici, plusieurs signatures sont autorisées, mais une seule implémentation est nécessaire. Cela peut prêter à confusion pour les développeurs familiers avec la surcharge classique.
Problème:
Une erreur courante consiste à essayer de définir plusieurs méthodes avec différents ensembles de paramètres. Cela entraîne une erreur de compilation, car TypeScript exige une implémentation qui réalise toutes les variantes de signatures.
Solution:
La surcharge est réalisée en déclarant plusieurs signatures de méthode, puis une implémentation qui correspond à toutes les variantes. Pour une distinction correcte des paramètres, on utilise généralement des gardiens de type ou instanceof.
Exemple de code :
class MyLogger { log(message: string): void; log(message: string, level: 'info' | 'error'): void; log(message: string, level?: 'info' | 'error'): void { const lvl = level ?? 'info'; console.log(`[${lvl}] ${message}`); } }
Caractéristiques clés :
Est-il possible d'implémenter deux implémentations d'une même méthode avec différents ensembles de paramètres ?
Non. En TypeScript, une seule implémentation est autorisée. Plusieurs méthodes avec le même nom entraînent une erreur de syntaxe.
Comment typiser les paramètres rest lors de la surcharge des méthodes, pour ne pas perdre le typage strict ?
Il est recommandé de décrire les paramètres exacts dans les signatures, et dans l'implémentation, d'utiliser les types les plus généraux :
class Test { doWork(a: number): void; doWork(a: string): void; doWork(a: number | string): void { //... } }
Que se passe-t-il si le type de retour des signatures surchargées est différent ?
TypeScript exigera que l'implémentation retourne un type union. Sinon, une erreur de compilation se produira.
class X { get(value: number): string; get(value: string): number; get(value: number | string): string | number { return typeof value === 'number' ? 'number' : 42; } }
Dans le produit, des tentatives ont été faites pour implémenter deux méthodes avec le même nom pour différents types de paramètres dans une classe. Après compilation, la méthode était "remplacée" par la dernière déclaration, toutes les autres versions étaient ignorées, et des bugs apparaissaient.
Avantages :
Inconvénients :
On a créé plusieurs signatures avec des paramètres de type union, puis dans la méthode, on a traité toutes les variantes via des gardiens de type. Le compilateur a immédiatement averti des problèmes de typage.
Avantages :
Inconvénients :