Les typeur prédicats sont une caractéristique syntaxique intéressante dans TypeScript. Bien qu’ils apparaissent au même endroit que les annotations de type de retour, ils ressemblent davantage à des phrases affirmatives courtes que à des annotations typiques, ce qui vous donne un meilleur contrôle sur la vérification du type.
Avec la sortie de TypeScript 5.5, travailler avec les typeur prédicats est devenu plus intuitif maintenant car il peut les inférer automatiquement dans de nombreux cas. Cependant, si vous naviguez dans des bases de code un peu plus anciennes, il est probable que vous rencontrez plus souvent des typeur prédicats écrits à la main.
Dans cet article, nous explorerons brièvement ce que sont les typeur prédicats et pourquoi ils sont utiles. Commençons par regarder le problème qu’ils résolvent.
Le problème
Je pense que la meilleure façon d’ understanding l’utilité des typeur prédicats est de remarquer les problèmes qui se posent lorsque nous n’en avons pas :
function isString(value: unknown): boolean {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string | number
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// string | number
}
Dans cet exemple, le type de retour de isString
est défini sur boolean
, et nous l’utilisons dans une fonction appelée padLeft
pour ajouter du padding à gauche sur une chaîne d’entrée. Le padding
peut être soit une chaîne donnée soit un nombre spécifié de caractères d’espace.
Vous vous demandez peut-être pourquoi j’ai codé en dur le type de retour en boolean
. C’est pour illustrer le problème. Si vous n’ajoutez pas d’annotation de type de retour et utilisez la dernière version de TypeScript, vous ne remarquerez aucun problème ici. Pour l’instant, supportez-moi – nous discuterons bientôt des différences liées aux versions.
La fonction fonctionnera sans problème à l’exécution, mais TypeScript ne peut effectuer aucun rétrécissement de type avec isString
. En conséquence, le type de padding
reste string | number
à la fois à l’intérieur et à l’extérieur de l’instruction if
. Cela conduit à un conflit avec l’attente de repeat
pour son premier argument, causant l’erreur de type.
La Solution : Entrée des Prédicats de Type
Même si vous n’êtes pas familier avec le terme prédicat, vous les avez probablement déjà utilisés. Les prédicats en programmation sont simplement des fonctions qui retournent un booléen pour répondre à une question oui/non. Plusieurs méthodes intégrées des tableaux JavaScript, telles que filter
, find
, every
et some
, utilisent des prédicats pour aider à la prise de décision.
Les prédicats de type sont un moyen de rendre les prédicats plus utiles pour le rétrécissement de type. Nous pouvons résoudre le problème en utilisant un prédicat de type comme type de retour :
function isString(value: unknown): value is string {
return typeof value === "string";
}
Ici, le prédicat de type est value is string
. Il dit trois choses :
-
La fonction est un prédicat. Donc TypeScript affichera une erreur si vous essayez de retourner autre chose qu’une valeur booléenne.
-
Si elle retourne
true
, alorsvalue
est de type chaîne de caractères. -
Si elle retourne
false
, alorsvalue
n’est pas de type chaîne de caractères.
Les prédicats de type permettent de créer des gardes de type personnalisées. Les gardes de type sont des vérifications logiques qui permettent de réduire les types à des types plus spécifiques, en d’autres termes, de les aiguiller. Donc, la fonction ci-dessus est également une garde de type personnalisée.
Voici le code complet :
function isString(value: unknown): value is string {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string
}
return " ".repeat(padding) + input;
// ^
// number
}
Ici, TypeScript réduit correctement le type de padding
à l’intérieur de l’instruction if
et en dehors d’elle.
Maintenant, essayons de voir brièvement comment les prédicats de type fonctionnaient avant TypeScript 5.5 et quelles améliorations cette version a apportées.
Les Prédicats de Type avant TypeScript 5.5
Dans notre exemple précédent, si nous n’indiquons pas de type de retour, il sera inféré comme boolean
:
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string | number
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// string | number
}
Ainsi, nous avons la même erreur que lorsque nous avons écrit manuellement le type de retour boolean
. Voici le lien vers le playground TypeScript pour le code fragment ci-dessus.allez et survolez les fonctions ou variables pour une meilleure compréhension des types. Ensuite, voyez comment l’écriture de la prédicande de type résout le problème.
Si nous n’ spécifions pas la prédicande de type, l’utilisation de méthodes comme filter
peut également entraîner une détection de type incorrecte :
function isString(value: unknown) {
return typeof value === "string";
}
const numsOrStrings = [1, 'hello', 2, 'world'];
// ^
// strings: (string | number)[]
const strings = numsOrStrings.filter(isString);
// ^
// strings: (string | number)[]
A présent, voyons comment TypeScript 5.5 améliore la situation.
Prédicandes de Type Après TypeScript 5.5
L’une des principales fonctionnalités de TypeScript 5.5 est qu’il peut inférer les prédicandes de type en analysant le corps de la fonction. Donc, si vous utilisez TypeScript 5.5 ou une version ultérieure, vous n’avez pas à écrire la prédicande de type comme type de retour pour isString
. TypeScript le fait pour vous, et le code comme celui que vous voyez dans l’exemple ci-dessous fonctionne parfaitement :
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// \^
// string
}
return " ".repeat(padding) + input; // Oups, erreur de type ici
// \^
// nombre
}
const numsOrStrings = [1, 'hello', 2, 'world'];
const strings = numsOrStrings.filter(isString);
// \^
// chaînes de caractères : string[]
const numbers = numsOrStrings.filter((v) => !isString(v));
// \^
// nombres : number[]
Je n’ai pas encore trouvé de situation où je suis mécontent de l’inference automatique de prédictions de type. Si vous en trouvez une, vous pouvez toujours écrire la vôtre manuellement.
Poursuite des études
Dans cet article, nous avons brièvement exploré les prédictions de type en TypeScript. Si vous êtes intéressé(e) à apprendre davantage et à comprendre les cas extrêmes, voici les guides officiels :
Merci d’avoir lu ! A bientôt pour la prochaine fois !
Le fond de l’image de couverture est de Mona Eendra sur Unsplash.
Source:
https://www.freecodecamp.org/news/what-are-type-predicates-in-typescript/