Les gardiens de type sont des mécanismes qui permettent de préciser le type d'une variable dans un bloc de code, basé sur certaines vérifications (par exemple, en utilisant typeof, instanceof, ou des fonctions spéciales retournant des expressions de type param is SomeType).
Le principal avantage est la sécurité et l'élimination des erreurs d'exécution grâce à la vérification des types au moment de la compilation.
Exemple :
interface Fish { swim: () => void } interface Bird { fly: () => void } function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; } function move(pet: Fish | Bird) { if (isFish(pet)) { pet.swim(); } else { pet.fly(); } }
Ici, la fonction isFish est un garde de type personnalisé.
Points particuliers :
Question : "Le compilateur TypeScript se fondera-t-il toujours uniquement sur la valeur de retour de la fonction guard, ou utilise-t-il également une analyse à l'intérieur de la fonction ?"
Réponse :
Le compilateur TypeScript s'appuie uniquement sur la signature de la valeur de retour param is Type. Ce qui se passe à l'intérieur de la fonction guard n'est pas analysé quant à la validité de l'implémentation.
Exemple (erreur dangereuse !) :
function isString(x: any): x is string { return true; } // Le compilateur considérera que c'est toujours une chaîne, même si ce n'est pas le cas : if (isString(123)) { // ici x est de type string, mais c'est en réalité un nombre }
Histoire
Dans un projet avec des DTO partagés entre le front-end et le back-end, on a oublié d'ajouter une vérification stricte à l'intérieur d'un garde de type personnalisé. En conséquence, certaines données étaient faussement perçues comme le type requis, entraînant des pannes côté client lorsqu'on essayait d'utiliser une propriété manquante.
Histoire
Un développeur a écrit un garde de type en se basant sur un champ optionnel, cependant la structure des données ne permettait pas d'avoir ce champ. Au final, le switch-case typé manquait d'une branche, et le compilateur ne lançait pas d'avertissement - des exceptions se produisaient à l'exécution.
Histoire
Dans l'un des services, lors du passage à TypeScript, on comptait uniquement sur les gardiens de type intégrés (typeof, instanceof). Lors du changement de prototype des objets, les vérifications devenaient incorrectes, ce qui a provoqué des bugs difficiles à déboguer en production.