IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Microsoft annonce la disponibilité de TypeScript 4.9
Qui se dote du nouvel opérateur « satisfies », améliore l'opérateur « in » et prend déjà en charge les accesseurs automatiques d'ECMAScript

Le , par Olivier Famien

55PARTAGES

6  0 
L’équipe de TypeScript vient d’annoncer la disponibilité de la version finale de TypeScript 4.9. Pour cette dernière version, de nombreuses améliorations appréciables sont au rendez-vous. Il s'agit entre autres de la prise en charge d’une fonctionnalité à venir dans ECMAScript nommée « auto-accessors », le renforcement des capacités de l’opérateur « in », l’ajout d’un nouvel opérateur nommé « satifies », et l’introduction de la commande « Remove Unused Imports », pour ne citer que celles-là.

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]function validate(someValue: number) {
return someValue !==[/code=typescript]...
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.

Une erreur dans cette actualité ? Signalez-nous-la !