L’opérateur satifies
Le nouvel opérateur satifies permet de valider que le type d’une expression correspond à un certain type sans changer le type résultant de cette expression. À titre d’exemple, on pourrait utiliser satifies pour valider que toutes les propriétés de palette sont compatibles avec string | number[]:
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | type Colors = "red" | "green" | "blue"; type RGB = [red: number, green: number, blue: number]; const palette = { red: [255, 0, 0], green: "#00ff00", bleu: [0, 0, 255] // ~~~~ The typo is now caught! } satisfies Record<Colors, string | RGB>; // Both of these methods are still accessible! const redComponent = palette.red.at(0); const greenNormalized = palette.green.toUpperCase(); |
L’opérateur satifies peut être utilisé pour détecter de nombreuses erreurs possibles. Par exemple, pour s’assurer qu’un objet possède toutes les clés d’un certain type, mais pas plus :
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | type Colors = "red" | "green" | "blue"; // Ensure that we have exactly the keys from 'Colors'. const favoriteColors = { "red": "yes", "green": false, "blue": "kinda", "platypus": false // ~~~~~~~~~~ error - "platypus" was never listed in 'Colors'. } satisfies Record<Colors, unknown>; // All the information about the 'red', 'green', and 'blue' properties are retained. const g: boolean = favoriteColors.green; |
Peut-être que cela ne nous intéresse pas de savoir si les noms de propriété correspondent d’une manière ou d’une autre, mais les types de chaque propriété sont assez importants pour effectuer des vérifications de type. Dans ce cas, nous pouvons également nous assurer que toutes les valeurs de propriété d’un objet sont conformes à un certain type.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | type RGB = [red: number, green: number, blue: number]; const palette = { red: [255, 0, 0], green: "#00ff00", blue: [0, 0] // ~~~~~~ error! } satisfies Record<string, string | RGB>; // Information about each property is still maintained. const redComponent = palette.red.at(0); const greenNormalized = palette.green.toUpperCase(); |
Limitation des propriétés non répertoriées avec l’opérateur in
En tant que développeur, il faut souvent gérer des valeurs qui ne sont pas entièrement connues au moment de l’exécution. En fait, nous ne savons souvent pas si des propriétés existent, si nous obtenons une réponse d’un serveur ou si nous lisons un fichier de configuration. L’opérateur in de JavaScript peut vérifier si une propriété existe sur un objet.
Auparavant, TypeScript nous permettait de restreindre tous les types qui ne répertorient pas explicitement une propriété.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | interface RGB { red: number; green: number; blue: number; } interface HSV { hue: number; saturation: number; value: number; } function setColor(color: RGB | HSV) { if ("hue" in color) { // 'color' now has the type HSV } // ... } |
Dans l’exemple ci-dessus, le type RGB n’a pas répertorié le hue et a été réduit, nous laissant avec le type HSV. Mais qu’en est-il des exemples où aucun type ne liste une propriété donnée ? Dans ces cas, le langage n’aide pas beaucoup. Prenons l’exemple suivant en JavaScript :
Code JavaScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | function tryGetPackageName(context) { const packageJSON = context.packageJSON; // Check to see if we have an object. if (packageJSON && typeof packageJSON === "object") { // Check to see if it has a string name property. if ("name" in packageJSON && typeof packageJSON.name === "string") { return packageJSON.name; } } return undefined; } |
Réécrire cela en TypeScript canonique serait simplement une question de définition et d’utilisation d’un type pour context; cependant, choisir un type sûr comme unknownpour la propriété packageJSONcauserait des problèmes dans les anciennes versions de TypeScript.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | interface Context { packageJSON: unknown; } function tryGetPackageName(context: Context) { const packageJSON = context.packageJSON; // Check to see if we have an object. if (packageJSON && typeof packageJSON === "object") { // Check to see if it has a string name property. if ("name" in packageJSON && typeof packageJSON.name === "string") { // ~~~~ // error! Property 'name' does not exist on type 'object. return packageJSON.name; // ~~~~ // error! Property 'name' does not exist on type 'object. } } return undefined; } |
En effet, alors que le type de packageJSON était réduit de unknown à object, l’opérateur in était strictement limité aux types qui définissaient réellement la propriété vérifiée. En conséquence, le type de packageJSONest resté object.
TypeScript 4.9 rend l’opérateur in un peu plus puissant lors de la réduction des types qui ne répertorient pas du tout la propriété. Au lieu de les laisser tels quels, le langage croisera leurs types avec Record<"property-key-being-checked", unknown>. Ainsi, dans l’exemple ci-dessus, packageJSONaura son type réduit de unknown à object & Record<"name", unknown>. Cela permet d’accéder directement à packageJSON.name et de réduire cela indépendamment.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | interface Context { packageJSON: unknown; } function tryGetPackageName(context: Context): string | undefined { const packageJSON = context.packageJSON; // Check to see if we have an object. if (packageJSON && typeof packageJSON === "object") { // Check to see if it has a string name property. if ("name" in packageJSON && typeof packageJSON.name === "string") { // Just works! return packageJSON.name; } } return undefined; } |
TypeScript 4.9 renforce également quelques contrôles sur la façon dont inest utilisé, garantissant que le côté gauche est attribuable au type string | number | symbol et que le côté droit est attribuable à object. Cela permet de vérifier que l’on utilise des clés de propriété valides et de ne pas vérifier accidentellement les primitives.
Les accesseurs automatiques dans les classes
TypeScript 4.9 prend en charge une fonctionnalité à venir dans ECMAScript appelée auto-accessors. Un auto-accessor ou accesseur automatique est une déclaration de champ qui sera transformée par le runtime en une paire d’accesseurs get et set qui accèdent à un champ de sauvegarde privé. Les autoaccesseurs sont déclarés comme les propriétés sur les classes, sauf qu’ils sont déclarés avec le mot clé accessor.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 | class Person { accessor name: string; constructor(name: string) { this.name = name; } } |
Ci-dessous, ces accesseurs automatiques transformés en get et set avec une propriété privée inaccessible.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Person { #__name: string; get name() { return this.#__name; } set name(value: string) { this.#__name = name; } constructor(name: string) { this.name = name; } } |
Vérifications d’égalité sur NaN
Un piège majeur pour les développeurs JavaScript est de vérifier la valeur NaN à l’aide des opérateurs d’égalité intégrés. Pour certains, NaN est une valeur numérique spéciale qui signifie "Not a Number". Rien n’est jamais égal à NaN– même NaN!
Code JavaScript : | Sélectionner tout |
1 2 3 4 5 | console.log(NaN == 0) // false console.log(NaN === 0) // false console.log(NaN == NaN) // false console.log(NaN === NaN) // false |
Mais au moins symétriquement tout est toujours non-égal à NaN.
Code JavaScript : | Sélectionner tout |
1 2 3 4 5 | console.log(NaN != 0) // true console.log(NaN !== 0) // true console.log(NaN != NaN) // true console.log(NaN !== NaN) // true |
Le problème est que le type numérique principal de JavaScript est un nombre à virgule flottante, et l’analyse des nombres en JavaScript peut souvent donner NaN. À son tour, effectuer une vérification par rapport à NaN finit par être assez courant, et la bonne façon de le faire est d’utiliser Number.isNaN; mais beaucoup de gens finissent accidentellement par vérifier plutôt avec someValue === NaN.
TypeScript se trompe désormais sur les comparaisons directes avec NaN, et suggérera plutôt d’utiliser une variante de Number.isNaN.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 | function validate(someValue: number) { return someValue !== NaN; // ~~~~~~~~~~~~~~~~~ // error: This condition will always return 'true'. // Did you mean '!Number.isNaN(someValue)'? } |
Ce changement devrait aider à détecter les erreurs de débutants, de la même manière que TypeScript émet actuellement des erreurs lors de comparaisons avec des littéraux d’objets et de tableaux.
Les commandes Remove Unused Imports et Sort Imports pour les éditeurs
Auparavant, TypeScript ne prenait en charge que deux commandes d’éditeur pour gérer les importations. Le premier s’appelait Organize Imports (ou Organiser les importations) qui supprimait les importations inutilisées, puis triait celles qui restaient. Dans TypeScript 4.3, une nouvelle commande appelée Sort Imports (ou Trier les importations) qui trie uniquement les importations dans le fichier, mais ne les supprime pas a été ajoutée. La mise en garde avec la commande Sort Imports était que dans Visual Studio Code, cette fonctionnalité n’était disponible qu’en tant que commande à l’enregistrement, et non en tant que commande déclenchable manuellement.
TypeScript 4.9 ajoute l’autre moitié et fournit désormais Remove Unsed Imports (pour Supprimer les importations inutilisées). TypeScript supprimera désormais les noms et instructions d’importation inutilisés, mais laissera par ailleurs l’ordre relatif.
Substitute remplacé par constraint sur les objets SubstitutionTypes
Dans le cadre d’une optimisation sur les types de substitution, les objets SubstitutionType ne contiennent plus la propriété substitute représentant la substitution effective (généralement une intersection du type de base et de la contrainte implicite) – au lieu de cela, ils contiennent simplement la propriété constraint .
Au-delà ce des nouveautés introduites dans cette dernière version de TypeScript, plusieurs autres améliorations sont également disponibles comme des améliorations de performances, des corrections de bogues et bien plus encore.
Source : Microsoft
Et vous ?
Avez-vous testé la nouvelle version de TypeScript ? répond-elle à vos attentes ?
Quelles sont les fonctionnalités que vous avez aimées le plus ou le moins dans cette dernière version de TypeScript ?
Voir aussi
TypeScript 4.9 Beta est disponible et apporte la restriction des propriétés non listées avec l’opérateur in, ainsi que la vérification de l’égalité sur NaN
TypeScript 4.7 Beta s’accompagne de la prise en charge du module ECMAScript dans Node.js et propose un contrôle de la détection de module
TypeScript 4.3 est disponible et apporte le mot-clé override pour qu’un dev puisse indiquer clairement s’il avait l’intention d’ajouter une nouvelle méthode ou de remplacer une méthode existante
Microsoft publie TypeScript 4.2 avec la prise en charge de Abstract Constructor Types et des contrôles plus stricts pour l’opérateur in