Leçons du module (1/2)
Gardes de Type
Le rétrécissement des types (Type Narrowing) est l'un des concepts les plus importants de TypeScript. Souvent, cependant, les gardiens de type standard comme typeof ou instanceof ne suffisent pas pour des objets personnalisés complexes. C'est là que les Gardiens de Type Personnalisés (Custom Type Guards) entrent en jeu.
Gardiens de Type Standard
Commençons par récapituler comment TypeScript restreint les types à l'aide des opérateurs JavaScript standard :
function processInput(val: string | number) {
if (typeof val === 'string') {
// Qui 'val' è di tipo string
console.log(val.toUpperCase());
} else {
// Qui 'val' è di tipo number
console.log(val.toFixed(2));
}
}Gardiens de Type Personnalisés (opérateur is)
Pour définir un gardien de type personnalisé, nous créons une fonction qui renvoie un prédicat de type au format parameterName is Type au lieu du type de retour booléen standard.
La fonction doit renvoyer un booléen (true ou false). Si elle renvoie true, TypeScript saura que le paramètre passé est du type spécifié.
interface Cat {
name: string;
meow(): void;
}
interface Dog {
name: string;
bark(): void;
}
// Questa è una guardia di tipo personalizzata
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeNoise(pet: Cat | Dog) {
if (isCat(pet)) {
// Qui TypeScript sa che 'pet' è un Cat
pet.meow();
} else {
// Qui TypeScript sa che 'pet' è un Dog
pet.bark();
}
}Sécurité et Casting (as vs Type Guards)
Le type casting (ex. val as Cat) force le compilateur à faire confiance au développeur, sans aucune vérification réelle à l'exécution. Si l'objet à l'exécution ne respecte pas les attentes, le code échouera silencieusement ou lèvera des exceptions.
Les gardiens de type personnalisés permettent au contraire d'exécuter un contrôle robuste et dynamique à l'exécution, informant en toute sécurité et précision le compilateur de TypeScript du type réel de la variable :
function processInput(input: unknown) {
// casting insicuro: potrebbe rompersi se input non ha il metodo split
// const str = input as string;
// console.log(str.split(' '));
// guardia sicura
if (isString(input)) {
console.log(input.split(' ')); // Sicuro al 100%!
}
}À toi de jouer
Exercice 1 : Gardien de Type pour Chaînes
Crée une fonction simple nommée isString qui fonctionne comme un gardien de type personnalisé pour vérifier si une valeur unknown est une chaîne de caractères.
Afficher l'indice
Le type de retour de la fonction doit être val is string, et tu dois utiliser typeof pour vérifier s'il est égal à 'string'.
Solution disponible après 3 tentatives
Exercice 2 : Gardien de Type pour Utilisateur Premium
Étant donné les types User et PremiumUser, écris une fonction de gardien de type isPremiumUser(user: User): user is PremiumUser qui vérifie si l'utilisateur a le rôle 'premium'.
Afficher l'indice
Définis la signature sous la forme function isPremiumUser(user: User): user is PremiumUser et compare user.role avec 'premium'.
Solution disponible après 3 tentatives
Exercice 3 : Vérification de l'Objet Erreur Personnalisé
Implémente la fonction isCustomError(err: unknown): err is CustomError qui vérifie si une valeur inconnue est un objet CustomError non nul qui possède la clé 'code'.
Afficher l'indice
Vérifie d'abord que typeof err est 'object' et n'est pas null, puis utilise l'opérateur 'in' pour vérifier la présence de la propriété 'code'.
Solution disponible après 3 tentatives
Exercice 4 : Gardien de Type Admin
Étant donné deux interfaces User (avec la propriété role: string) et Admin (qui étend User et a une propriété adminToken: string), écris une fonction gardienne de type nommée isAdmin qui accepte un objet user de type User et renvoie un prédicat de type user is Admin. Le gardien doit vérifier que le role de l'utilisateur est égal à 'admin'.
Afficher l'indice
Définis la signature sous la forme function isAdmin(user: User): user is Admin et contrôle que user.role === 'admin'.
Solution disponible après 3 tentatives