« Aujourd'hui, nous sommes ravis d'annoncer notre Release Candidate (RC) de TypeScript 4.4 ! Entre maintenant et la version stable de TypeScript 4.4, nous n'attendons aucun autre changement en dehors des corrections de bogues critiques ».Types de propriétés facultatifs exacts (--exactOptionalPropertyTypes)
En JavaScript, la lecture d'une propriété manquante sur un objet produit la valeur undefined. Il est également possible d'avoir une propriété réelle avec la valeur undefined. Beaucoup de code en JavaScript a tendance à traiter ces situations de la même manière, et donc initialement, TypeScript a simplement interprété chaque propriété facultative comme si un utilisateur avait écrit undefined dans le type. Par exemple,
| Code TypeScript : | Sélectionner tout |
1 2 3 4 | interface Person { name: string, age?: number; } |
était considérée comme équivalente à
| Code TypeScript : | Sélectionner tout |
1 2 3 4 | interface Person { name: string, age?: number | undefined; } |
Cela signifiait qu'un utilisateur pouvait explicitement écrire undefined à la place de age.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 | const p: Person = { name: "Daniel", age: undefined, // This is okay by default. }; |
Ainsi, par défaut, TypeScript ne fait pas la distinction entre une propriété actuelle avec la valeur undefined et une propriété manquante. Bien que cela fonctionne la plupart du temps, tout le code en JavaScript ne fait pas les mêmes hypothèses. Les fonctions et opérateurs tels que Object.assign, Object.keys, ({ ...obj }) et les boucles for–in se comportent différemment selon qu'une propriété existe ou non sur un objet. Dans le cas de notre exemple Person, cela pourrait potentiellement conduire à des erreurs d'exécution si la propriété age était observée dans un contexte où sa présence était importante.
Dans TypeScript 4.4, le nouvel indicateur --exactOptionalPropertyTypes spécifie que les types de propriétés facultatifs doivent être interprétés exactement comme écrits, ce qui signifie que | undefined n'est pas ajouté au type*:
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 | // With 'exactOptionalPropertyTypes' on: const p: Person = { name: "Daniel", age: undefined, // Error! undefined isn't a number }; |
Ce drapeau ne fait pas partie de la famille --strict et doit être activé explicitement si vous souhaitez ce comportement. Cela nécessite également que --strictNullChecks soit également activé. L'équipe va mettre à jour DefinitelyTyped et d'autres définitions pour essayer de rendre la transition aussi simple que possible, mais vous pouvez rencontrer des frictions avec cela selon la façon dont votre code est structuré.
Blocs static dans les classes
TypeScript 4.4 prend en charge les blocs statiques dans les classes, une fonctionnalité ECMAScript à venir qui peut vous aider à écrire un code d'initialisation plus complexe pour les membres statiques.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | class Foo { static count = 0; // This is a static block: static { if (someCondition()) { count++; } } } |
Ces blocs statiques vous permettent d'écrire une séquence d'instructions avec leur propre portée pouvant accéder aux champs privés de la classe conteneur. Cela signifie que nous pouvons écrire du code d'initialisation avec toutes les capacités d'écriture d'instructions, aucune fuite de variables et un accès complet aux composants internes de notre classe.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Foo { static #count = 0; get count() { return this.#count; } static { try { const lastInstances = loadLastInstances(); count += lastInstances.length; } catch {} } } |
Sans blocs static, l'écriture du code ci-dessus était possible, mais impliquait souvent plusieurs types de piratages différents qui devaient être compromis d'une manière ou d'une autre. Notez qu'une classe peut avoir plusieurs blocs static et qu'ils sont exécutés dans le même ordre dans lequel ils sont écrits.
| Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // Prints: // 1 // 2 // 3 class Foo { static prop = 1 static { console.log(1); } static { console.log(2); } static { console.log(3); } } |
Analyse du flux de contrôle des conditions d'alias
En 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...
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.