Quoi de neuf dans TypeScript 5.0 : déclarateurs, type const, amélioration des énumérations, vitesse et bien plus encore !

Publié: 2023-04-15

TypeScript 5.0 a été officiellement publié le 16 mars 2023 et est désormais disponible pour tout le monde. Cette version introduit de nombreuses nouvelles fonctionnalités dans le but de rendre TypeScript plus petit, plus simple et plus rapide.

Cette nouvelle version modernise les décorateurs pour la personnalisation des classes, permettant la personnalisation des classes et de leurs membres de manière réutilisable. Les développeurs peuvent désormais ajouter un modificateur const à une déclaration de paramètre de type, permettant aux inférences de type const d'être la valeur par défaut. La nouvelle version transforme également toutes les énumérations en énumérations, simplifiant la structure du code et accélérant l'expérience TypeScript.

Dans cet article, vous explorerez les modifications introduites dans TypeScript 5.0, en fournissant un aperçu approfondi de ses nouvelles fonctionnalités et capacités.

Premiers pas avec TypeScript 5.0

TypeScript est un compilateur officiel que vous pouvez installer dans votre projet à l'aide de npm. Si vous souhaitez commencer à utiliser TypeScript 5.0 dans votre projet, vous pouvez exécuter la commande suivante dans le répertoire de votre projet :

 npm install -D typescript

Cela installera le compilateur dans le répertoire node_modules , que vous pouvez maintenant exécuter avec la commande npx tsc .

Vous pouvez également trouver des instructions sur l'utilisation de la nouvelle version de TypeScript dans Visual Studio Code dans cette documentation.

ICYMI : TypeScript 5.0 est là ! Explorez ses mises à jour passionnantes telles que les déclarateurs, le type de const et les énumérations améliorées dans ce guide Cliquez pour tweeter

Quoi de neuf dans TypeScript 5.0 ?

Dans cet article, explorons 5 mises à jour majeures introduites dans TypeScript. Ces fonctionnalités incluent :

Décorateurs modernisés

Les décorateurs existent depuis un certain temps dans TypeScript sous un drapeau expérimental, mais la nouvelle version les met à jour avec la proposition ECMAScript, qui est maintenant à l'étape 3, ce qui signifie qu'elle est à une étape où elle est ajoutée à TypeScript.

Les décorateurs sont un moyen de personnaliser le comportement des classes et de leurs membres de manière réutilisable. Par exemple, si vous avez une classe qui a deux méthodes, greet et getAge :

 class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } greet() { console.log(`Hello, my name is ${this.name}.`); } getAge() { console.log(`I am ${this.age} years old.`); } } const p = new Person('Ron', 30); p.greet(); p.getAge();

Dans les cas d'utilisation réels, cette classe devrait avoir des méthodes plus compliquées qui gèrent une certaine logique asynchrone et ont des effets secondaires, etc., où vous voudriez lancer des appels console.log pour aider à déboguer les méthodes.

 class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } greet() { console.log('LOG: Method Execution Starts.'); console.log(`Hello, my name is ${this.name}.`); console.log('LOG: Method Execution Ends.'); } getAge() { console.log('LOG: Method Execution Starts.'); console.log(`I am ${this.age} years old.`); console.log('Method Execution Ends.'); } } const p = new Person('Ron', 30); p.greet(); p.getAge();

Il s'agit d'un modèle fréquent, et il serait pratique d'avoir une solution à appliquer à chaque méthode.

C'est là que les décorateurs entrent en jeu. Nous pouvons définir une fonction nommée debugMethod qui apparaît comme suit :

 function debugMethod(originalMethod: any, context: any) { function replacementMethod(this: any, ...args: any[]) { console.log('Method Execution Starts.'); const result = originalMethod.call(this, ...args); console.log('Method Execution Ends.'); return result; } return replacementMethod; }

Dans le code ci-dessus, debugMethod prend la méthode d'origine ( originalMethod ) et renvoie une fonction qui effectue les opérations suivantes :

  1. Consigne un message "L'exécution de la méthode démarre.".
  2. Passe la méthode d'origine et tous ses arguments (y compris celui-ci).
  3. Consigne un message "Method Execution Ends.".
  4. Renvoie quelle que soit la méthode d'origine renvoyée.

En utilisant des décorateurs, vous pouvez appliquer le debugMethod à vos méthodes comme indiqué dans le code ci-dessous :

 class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } @debugMethod greet() { console.log(`Hello, my name is ${this.name}.`); } @debugMethod getAge() { console.log(`I am ${this.age} years old.`); } } const p = new Person('Ron', 30); p.greet(); p.getAge();

Cela affichera ce qui suit :

 LOG: Entering method. Hello, my name is Ron. LOG: Exiting method. LOG: Entering method. I am 30 years old. LOG: Exiting method.

Lors de la définition de la fonction décoratrice ( debugMethod ), un deuxième paramètre est passé appelé context (c'est l'objet context — contient des informations utiles sur la façon dont la méthode décorée a été déclarée ainsi que le nom de la méthode). Vous pouvez mettre à jour votre debugMethod pour obtenir le nom de la méthode à partir de l'objet context :

 function debugMethod( originalMethod: any, context: ClassMethodDecoratorContext ) { const methodName = String(context.name); function replacementMethod(this: any, ...args: any[]) { console.log(`'${methodName}' Execution Starts.`); const result = originalMethod.call(this, ...args); console.log(`'${methodName}' Execution Ends.`); return result; } return replacementMethod; }

Lorsque vous exécutez votre code, la sortie portera désormais le nom de chaque méthode décorée avec le décorateur debugMethod :

 'greet' Execution Starts. Hello, my name is Ron. 'greet' Execution Ends. 'getAge' Execution Starts. I am 30 years old. 'getAge' Execution Ends.

Il y a plus à ce que vous pouvez faire avec les décorateurs. N'hésitez pas à consulter la pull request d'origine pour plus d'informations sur l'utilisation des décorateurs dans TypeScript.

Présentation des paramètres de type const

Il s'agit d'une autre version importante qui vous offre un nouvel outil avec des génériques afin d'améliorer l'inférence que vous obtenez lorsque vous appelez des fonctions. Par défaut, lorsque vous déclarez des valeurs avec const , TypeScript déduit le type et non ses valeurs littérales :

 // Inferred type: string[] const names = ['John', 'Jake', 'Jack'];

Jusqu'à présent, pour obtenir l'inférence souhaitée, vous deviez utiliser l'assertion const en ajoutant « as const » :

 // Inferred type: readonly ["John", "Jake", "Jack"] const names = ['John', 'Jake', 'Jack'] as const;

Lorsque vous appelez des fonctions, c'est similaire. Dans le code ci-dessous, le type de pays déduit est string[] :

 type HasCountries = { countries: readonly string[] }; function getCountriesExactly(arg: T): T['countries'] { return arg.countries; } // Inferred type: string[] const countries = getCountriesExactly({ countries: ['USA', 'Canada', 'India'] });

Vous pouvez souhaiter un type plus spécifique dont une façon de corriger jusqu'à présent a été d'ajouter l'assertion as const :

 // Inferred type: readonly ["USA", "Canada", "India"] const names = getNamesExactly({ countries: ['USA', 'Canada', 'India'] } as const);

Cela peut être difficile à retenir et à mettre en œuvre. Cependant, TypeScript 5.0 introduit une nouvelle fonctionnalité dans laquelle vous pouvez ajouter un modificateur const à une déclaration de paramètre de type, qui appliquera automatiquement une inférence de type const par défaut.

 type HasCountries = { countries: readonly string[] }; function getNamesExactly(arg: T): T['countries'] { return arg.countries; } // Inferred type: readonly ["USA", "Canada", "India"] const names = getNamesExactly({ countries: ['USA', 'Canada', 'India'] });

L'utilisation de paramètres de type const permet aux développeurs d'exprimer plus clairement leur intention dans leur code. Si une variable est censée être constante et ne jamais changer, l'utilisation d'un paramètre de type const garantit qu'elle ne pourra jamais être modifiée accidentellement.

Vous pouvez consulter la demande d'extraction d'origine pour plus d'informations sur le fonctionnement du paramètre de type const dans TypeScript.

Améliorations des énumérations

Les énumérations dans TypeScript sont une construction puissante qui permet aux développeurs de définir un ensemble de constantes nommées. Dans TypeScript 5.0, des améliorations ont été apportées aux énumérations pour les rendre encore plus flexibles et utiles.

Par exemple, si vous avez l'énumération suivante passée dans une fonction :

 enum Color { Red, Green, Blue, } function getColorName(colorLevel: Color) { return colorLevel; } console.log(getColorName(1));

Avant l'introduction de TypeScript 5.0, vous pouviez transmettre un mauvais numéro de niveau et cela ne générerait aucune erreur. Mais avec l'introduction de TypeScript 5.0, il lancera immédiatement une erreur.

En outre, la nouvelle version transforme toutes les énumérations en énumérations d'union en créant un type unique pour chaque membre calculé. Cette amélioration permet de restreindre toutes les énumérations et de référencer leurs membres en tant que types :

 enum Color { Red, Purple, Orange, Green, Blue, Black, White, } type PrimaryColor = Color.Red | Color.Green | Color.Blue; function isPrimaryColor(c: Color): c is PrimaryColor { return c === Color.Red || c === Color.Green || c === Color.Blue; } console.log(isPrimaryColor(Color.White)); // Outputs: false console.log(isPrimaryColor(Color.Red)); // Outputs: true

Améliorations des performances de TypeScript 5.0

TypeScript 5.0 inclut de nombreux changements importants dans la structure du code, les structures de données et les extensions algorithmiques. Cela a contribué à améliorer l'ensemble de l'expérience TypeScript, de l'installation à l'exécution, en la rendant plus rapide et plus efficace.

Par exemple, la différence entre la taille du package de TypeScript 5.0 et 4.9 est assez impressionnante.

TypeScript a récemment été migré des espaces de noms vers les modules, ce qui lui permet de tirer parti des outils de construction modernes capables d'effectuer des optimisations telles que le levage de portée. De plus, la suppression de certains codes obsolètes a réduit d'environ 26,4 Mo la taille du package de 63,8 Mo de TypeScript 4.9.

Taille du paquet TypeScript
Taille du paquet TypeScript

Voici quelques victoires plus intéressantes en termes de vitesse et de taille entre TypeScript 5.0 et 4.9 :

Scénario Temps ou taille par rapport à TS 4.9
temps de construction de material-ui 90%
Heure de démarrage du compilateur TypeScript 89%
Temps de construction du dramaturge 88%
Temps d'auto-construction du compilateur TypeScript 87%
Temps de génération d'Outlook Web 82%
Temps de construction du code VS 80%
dactylographié npm Taille du paquet 59%

Résolution de bundler pour une meilleure résolution de module

Lorsque vous écrivez une instruction d'importation dans TypeScript, le compilateur doit savoir à quoi l'importation fait référence. Il le fait en utilisant la résolution du module. Par exemple, lorsque vous écrivez import { a } from "moduleA" , le compilateur a besoin de connaître la définition de a dans moduleA pour vérifier son utilisation.

Dans TypeScript 4.7, deux nouvelles options ont été ajoutées pour les paramètres --module et moduleResolution : node16 et nodenext .

Le but de ces options était de représenter plus précisément les règles de recherche exactes pour les modules ECMAScript dans Node.js. Cependant, ce mode comporte plusieurs restrictions qui ne sont pas appliquées par d'autres outils.

Par exemple, dans un module ECMAScript dans Node.js, toute importation relative doit inclure une extension de fichier pour fonctionner correctement :

 import * as utils from "./utils"; // Wrong import * as utils from "./utils.mjs"; // Correct

TypeScript a introduit une nouvelle stratégie appelée "moduleResolution bundler". Cette stratégie peut être mise en œuvre en ajoutant le code suivant dans la section « compilerOptions » de votre fichier de configuration TypeScript :

 { "compilerOptions": { "target": "esnext", "moduleResolution": "bundler" } }

Cette nouvelle stratégie convient à ceux qui utilisent des bundles modernes tels que Vite, esbuild, swc, Webpack, Parcel et d'autres qui utilisent une stratégie de recherche hybride.

Vous pouvez vérifier la demande d'extraction d'origine et son implémentation pour plus d'informations sur le fonctionnement du bundle moduleResolution dans TypeScript.

Dépréciations

TypeScript 5.0 est livré avec une certaine dépréciation, y compris les exigences d'exécution, les modifications de lib.d.ts et les modifications de rupture de l'API.

  1. Exigences d'exécution : TypeScript cible désormais ECMAScript 2018 et le package définit une attente minimale du moteur de 12.20. Par conséquent, les utilisateurs de Node.js doivent disposer d'une version minimale de 12.20 ou d'une version ultérieure pour utiliser TypeScript 5.0.
  2. Changements de lib.d.ts : Il y a eu quelques changements dans la façon dont les types pour le DOM sont générés, ce qui peut affecter le code existant. En particulier, certaines propriétés ont été converties de nombre en types littéraux numériques, et les propriétés et méthodes de gestion des événements couper, copier et coller ont été déplacées d'une interface à l'autre.
  3. Modifications majeures de l'API : certaines interfaces inutiles ont été supprimées et certaines améliorations d'exactitude ont été apportées. TypeScript 5.0 est également passé aux modules.

TypeScript 5.0 a déprécié certains paramètres et leurs valeurs correspondantes, notamment target: ES3 , out , noImplicitUseStrict , keyofStringsOnly , suppressExcessPropertyErrors , suppressImplicitAnyIndexErrors , noStrictGenericChecks , charset , importsNotUsedAsValues ​​et preserveValueImports , ainsi que préfixe dans les références de projet.

Bien que ces configurations restent valides jusqu'à TypeScript 5.5, un avertissement sera émis pour alerter les utilisateurs qui les utilisent encore.

TypeScript 5.0 est plus simple, plus rapide et plus petit ! Explorez les changements qui révolutionneront votre jeu de codage ici. Cliquez pour tweeter

Résumé

Dans cet article, vous avez découvert certaines des principales fonctionnalités et améliorations apportées par TypeScript 5.0, telles que les améliorations apportées aux énumérations, à la résolution du bundle et aux paramètres de type const, ainsi que des améliorations de la vitesse et de la taille.

Si vous songez à TypeScript pour vos prochains projets, essayez gratuitement l'hébergement d'applications de Kinsta.

Maintenant c'est ton tour! Quelles fonctionnalités ou améliorations trouvez-vous les plus attrayantes dans TypeScript 5.0 ? Y en a-t-il d'importants que nous avons peut-être oubliés? Faites le nous savoir dans les commentaires.