Analyse du flux de contrôle des conditions d'aliasEn JavaScript, nous devons souvent sonder une variable de différentes manières pour voir si elle a un type plus spécifique que nous pouvons utiliser. TypeScript comprend ces vérifications et les appelle des gardes de type. Au lieu d'avoir à convaincre TypeScript du type d'une variable chaque fois que nous l'utilisons, le vérificateur de type s'appuie sur ce qu'on appelle l'analyse de flux de contrôle pour déduire le type dans chaque construction de langage.
Par exemple, nous pouvons écrire quelque chose comme :
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 | function foo(arg: unknown) { if (typeof arg === "string") { // We know this is a string now. console.log(arg.toUpperCase()); } } |
Dans cet exemple, nous avons vérifié si arg était un string. TypeScript a reconnu la vérification de typeof arg === "string", qu'il considérait comme une protection de type, et a pu déterminer que arg devrait être un string dans le corps du bloc if.
Cependant, que se passe-t-il si nous déplaçons la condition vers une constante ?
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 | function foo(arg: unknown) { const argIsString = typeof arg === "string"; if (argIsString) { console.log(arg.toUpperCase()); // ~~~~~~~~~~~ // Error! Property 'toUpperCase' does not exist on type 'unknown'. } } |
Dans les versions précédentes de TypeScript, cela aurait conduit à une erreur – même si argIsString avait reçu la valeur garde de type, TypeScript perdait simplement cette information. C'est dommage, car nous pourrions vouloir réutiliser la même vérification à plusieurs endroits. Pour contourner ce problème, les utilisateurs doivent souvent se répéter ou utiliser des assertions de type (casts).
Dans TypeScript 4.4, ce n'est plus le cas. L'exemple ci-dessus fonctionne sans erreur ! Lorsque TypeScript voit que nous testons une valeur constante, il effectuera un peu de travail supplémentaire pour voir s'il contient une protection de type. Si cette protection de type opère sur un const, une propriété readonly ou un paramètre non modifié, alors TypeScript est capable de restreindre cette valeur de manière appropriée.
Différentes sortes de conditions de garde de type sont préservées – pas seulement des vérifications typeof. Par exemple, les contrôles sur les syndicats discriminés fonctionnent comme un charme.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | type Shape = | { kind: "circle", radius: number } | { kind: "square", sideLength: number }; function area(shape: Shape): number { const isCircle = shape.kind === "circle"; if (isCircle) { // We know we have a circle here! return Math.PI * shape.radius ** 2; } else { // We know we're left with a square here! return shape.sideLength ** 2; } } |
Comme autre exemple, voici une fonction qui vérifie si deux de ses entrées ont un contenu.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | function doSomeChecks( inputA: string | undefined, inputB: string | undefined, shouldDoExtraWork: boolean, ) { let mustDoWork = inputA && inputB && shouldDoExtraWork; if (mustDoWork) { // Can access 'string' properties on both 'inputA' and 'inputB'! const upperA = inputA.toUpperCase(); const upperB = inputB.toUpperCase(); // ... } } |
TypeScript peut comprendre que inputA et inputB sont tous deux présents si mustDoWork est true. Cela signifie que nous n'avons pas à écrire une assertion non nulle comme inputA! pour convaincre TypeScript que inputA est undefined.
Une caractéristique intéressante ici est que cette analyse fonctionne de manière transitive. Si nous avons une constante affectée à une condition qui contient plus de constantes et que ces constantes sont chacune affectées à des gardes de type, alors TypeScript peut propager les conditions plus tard.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | function f(x: string | number | boolean) { const isString = typeof x === "string"; const isNumber = typeof x === "number"; const isStringOrNumber = isString || isNumber; if (isStringOrNumber) { x; // Type of 'x' is 'string | number'. } else { x; // Type of 'x' is 'boolean'. } } |
Notez qu'il y a une limite - TypeScript ne va pas arbitrairement en profondeur lors de la vérification de ces conditions, mais son analyse est suffisamment approfondie pour la plupart des vérifications.
Cette fonctionnalité devrait permettre à beaucoup de code JavaScript intuitif de «*fonctionner*» dans TypeScript sans que cela ne vous gêne.
Signatures d'index Template String Pattern et symbol
TypeScript nous permet de décrire des objets où chaque propriété doit avoir un certain type à l'aide de signatures d'index. Cela nous permet d'utiliser ces objets comme des types de...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.