Annonce de TypeScript 6.0
(devblogs.microsoft.com)- Dernière release de l’actuelle base de code JavaScript et release de transition préparant le passage à TypeScript 7.0, le port natif écrit en Go
- Améliorations de l’inférence de types et de la résolution de modules, dont un assouplissement de la sensibilité au contexte pour les fonctions qui n’utilisent pas
this, ainsi que la prise en charge des subpath imports commençant par#/ - Modernisation majeure des valeurs par défaut des options du compilateur :
strictpasse àtrue,targetàes2025,typesà[], etc. - Dépréciation massive d’options legacy comme la cible ES5, les modules AMD/UMD/SystemJS,
--baseUrl,--moduleResolution node10, etc. - Ajout de la prise en charge des types pour les propositions ECMAScript Stage 4 les plus récentes, comme l’API Temporal,
getOrInsert/getOrInsertComputeddeMap, ou encoreRegExp.escape
Positionnement de TypeScript 6.0
- Dernière release basée sur l’actuelle base de code JavaScript, elle sert de pont vers TypeScript 7.0 (port natif en Go)
- TypeScript 7.0 exploite le code natif et le multithreading à mémoire partagée, et il est déjà tout proche d’être finalisé
- La plupart des changements de la 6.0 visent à aligner et préparer l’adoption de la 7.0
- TypeScript 7.0 peut déjà être testé via l’extension VS Code ou le package npm
Changements depuis la Beta et la RC
- Ajustement du type checking des expressions de fonction dans les appels génériques (en particulier les expressions JSX génériques) — cela permet de détecter davantage de bugs dans le code existant, mais certains appels génériques peuvent désormais nécessiter des arguments de type explicites
- Extension de la dépréciation de la syntaxe d’import assertion (
assert) aux appelsimport() - Mise à jour des types DOM — prise en compte des standards Web les plus récents, avec des ajustements liés à l’API Temporal
Assouplissement de la sensibilité au contexte pour les fonctions qui n’utilisent pas this
- Lors de l’inférence des types, TypeScript classe les fonctions ayant des paramètres sans type explicite comme des fonctions contextuellement sensibles (contextually sensitive function) et leur donne une priorité plus basse dans l’ordre d’inférence
- Les fonctions écrites avec une syntaxe de méthode avaient toujours un paramètre implicite
this, et étaient donc toujours considérées comme contextuellement sensibles, contrairement aux fonctions fléchées- Cela pouvait faire échouer l’inférence de types selon l’ordre des méthodes dans un littéral objet
- Dans TypeScript 6.0, les fonctions qui n’utilisent pas réellement
thisne sont plus considérées comme contextuellement sensibles- Leur priorité augmente dans l’inférence de types, ce qui permet une inférence correcte quel que soit l’ordre des méthodes
- Implémenté grâce à une contribution de Mateusz Burzyński
Prise en charge des Subpath Imports commençant par #/
- La fonctionnalité subpath imports de Node.js permet de définir des alias vers des modules internes d’un package via le champ
importsdupackage.json - Jusqu’ici, un caractère était obligatoire après
#, ce qui empêchait l’utilisation de chemins commençant par#/- Cela créait de la confusion pour les développeurs habitués à la convention de préfixe
@/dans les bundlers
- Cela créait de la confusion pour les développeurs habitués à la convention de préfixe
- Node.js a récemment commencé à prendre en charge les subpath imports commençant par
#/- Cela permet des mappings plus concis de la forme
"#/*": "./dist/*"
- Cela permet des mappings plus concis de la forme
- TypeScript 6.0 les prend en charge avec les options
--moduleResolution nodenextetbundler - Implémenté grâce à une contribution de magic-akari
Autorisation de la combinaison --moduleResolution bundler et --module commonjs
- Jusqu’ici,
--moduleResolution bundlerne pouvait être utilisé qu’avec--module esnextou--module preserve - Avec la dépréciation de
--moduleResolution node(node10), cette nouvelle combinaison constitue le chemin de mise à niveau le plus adapté pour de nombreux projets - À long terme, il est recommandé de migrer vers
--module preserve+--moduleResolution bundlerou vers--module nodenext
Flag --stableTypeOrdering
- En interne, les ID de type attribués par TypeScript dépendent de l’ordre de traitement, et servent ensuite à trier les types union
- Cela pouvait entraîner des comportements imprévisibles où le résultat de l’emit des déclarations variait selon l’ordre des déclarations
- TypeScript 7.0 introduisant le type checking parallèle, il utilise un algorithme de tri déterministe basé sur le contenu pour résoudre les problèmes d’attribution d’ID non déterministes
- Exemple :
100 | 500sera toujours émis dans le même ordre
- Exemple :
- Activer
--stableTypeOrderingdans la 6.0 permet d’aligner le comportement de tri des types sur celui de la 7.0 et de réduire les écarts entre les deux bases de code- Cela peut provoquer jusqu’à 25 % de baisse de performances lors du type checking
- En cas d’erreurs de types dues à des différences d’inférence, il est possible de corriger en ajoutant des arguments de type explicites ou des annotations de variables
- Ce flag est prévu uniquement pour diagnostiquer la migration de la 6.0 vers la 7.0 et son usage prolongé est déconseillé
Option es2025 (target et lib)
- ES2025 n’introduit pas de nouvelles fonctionnalités du langage JavaScript, mais ajoute des types d’API intégrées (par exemple
RegExp.escape) - Des éléments auparavant dans
esnext, commePromise.try, les méthodes deIteratoret celles deSet, sont déplacés verses2025 - Implémenté grâce à une contribution de Kenta Moriuchi
Prise en charge des types pour l’API Temporal
- Les types intégrés de la proposition Temporal, désormais au Stage 4, sont inclus dans TypeScript 6.0
- Disponibles avec
--target esnextou"lib": ["esnext"](ou plus finementesnext.temporal) - Les API comme
Temporal.Now.instant().subtract()ou.add()peuvent être utilisées avec une sécurité de typage - Déjà disponible dans plusieurs runtimes, Temporal fait désormais officiellement partie du langage JavaScript grâce à son passage au Stage 4
- Implémenté grâce à une contribution de Renegade334
Prise en charge des types pour les méthodes d’"upsert" de Map (getOrInsert / getOrInsertComputed)
- Cela simplifie le motif répétitif consistant à vérifier si une clé existe dans une
Mapet, sinon, à y définir une valeur par défaut - La proposition ECMAScript d’"upsert" est passée au Stage 4, ajoutant deux nouvelles méthodes à
MapetWeakMapgetOrInsert: insère puis renvoie la valeur par défaut spécifiée si la clé est absentegetOrInsertComputed: calcule la valeur par défaut à la demande via un callback lorsque son coût de création est élevé- Le callback reçoit la clé en argument, ce qui permet aussi de générer une valeur par défaut dépendant de la clé
- Ajoutées à la lib
esnext, elles sont immédiatement utilisables dans TypeScript 6.0 - Implémenté grâce à une contribution de Renegade334
RegExp.escape
- La fonction
RegExp.escape, qui échappe les caractères spéciaux dans les expressions régulières, est passée au Stage 4 - Elle est incluse dans la lib
es2025et peut être utilisée dans TypeScript 6.0 - Implémenté grâce à une contribution de Kenta Moriuchi
Intégration de dom.iterable et dom.asynciterable dans la lib dom
- Jusqu’ici, pour utiliser l’itération sur
NodeList,HTMLCollection, etc., il fallait préciser"lib": ["dom", "dom.iterable"] - Dans TypeScript 6.0, le contenu de
lib.dom.iterable.d.tsetlib.dom.asynciterable.d.tsest entièrement intégré danslib.dom.d.tsdom.iterableetdom.asynciterablerestent référencables, mais sont désormais des fichiers vides
- Tous les principaux navigateurs modernes prenant déjà en charge ces fonctionnalités, il s’agit d’une amélioration de confort qui supprime une source fréquente de confusion
Principaux changements de valeurs par défaut
strictvaut désormaistruepar défaut : comme la plupart des nouveaux projets veulent le mode strict, les projets qui dépendaient defalsedoivent maintenant définir explicitement"strict": falsemodulevaut désormaisesnextpar défaut : cela reflète la domination d’ESM comme format de moduletargetpointe par défaut vers la dernière version d’ES (actuellementes2025) : avec la généralisation des runtimes evergreen, le transpile vers d’anciennes versions devient inutilenoUncheckedSideEffectImportsvaut désormaistruepar défaut : cela aide à détecter les fautes de frappe dans les imports uniquement destinés aux effets de bordlibReplacementvaut désormaisfalsepar défaut : cela améliore les performances par défaut en évitant des échecs inutiles de résolution de modules et davantage de fichiers surveillés
rootDir passe à . par défaut
- Jusqu’ici, quand il n’était pas précisé, il était déterminé en inférant le répertoire commun à tous les fichiers d’entrée non déclaratifs
- Cela impliquait de charger et parser le projet pour déterminer si un fichier en faisait partie
- Dans TypeScript 6.0, la valeur par défaut devient le répertoire contenant
tsconfig.json - Si les fichiers sources se trouvent plus profondément que
tsconfig.json, il faut définir explicitement"rootDir": "./src", par exemple- Sinon, on peut obtenir une structure de sortie non souhaitée comme
./dist/src/index.js
- Sinon, on peut obtenir une structure de sortie non souhaitée comme
types passe à [] par défaut
- Jusqu’ici, tous les packages présents dans
node_modules/@typesétaient inclus automatiquement, ce qui ajoutait un important surcoût au temps de build- Dans un dépôt classique, il est fréquent que des centaines de packages
@typessoient inclus transitivement
- Dans un dépôt classique, il est fréquent que des centaines de packages
- Dans TypeScript 6.0, la valeur par défaut devient
[](tableau vide), ce qui évite de charger des fichiers de déclarations inutiles - Des cas concrets montrent des améliorations du temps de build de 20 à 50 %
- La plupart des projets devront définir explicitement
"types": ["node"]ou"types": ["node", "jest"], par exemple- Il est possible de restaurer l’ancien comportement avec
"types": ["*"]
- Il est possible de restaurer l’ancien comportement avec
Éléments dépréciés (Deprecation)
Dépréciation de target: es5
- La cible ES5 n’a presque plus de cas d’usage depuis la disparition d’IE et la généralisation des navigateurs evergreen
- La cible minimale passe à ES2015 ; si une sortie ES5 est nécessaire, il est recommandé d’utiliser un compilateur externe
Dépréciation de --downlevelIteration
- Cette option n’avait d’effet qu’avec l’emit ES5 ; avec la dépréciation de la cible ES5, elle perd donc sa raison d’être
Dépréciation de --moduleResolution node (node10)
- Elle reflétait l’algorithme de résolution de modules de Node.js 10, désormais en décalage avec le comportement des versions modernes de Node.js
- Il est recommandé de migrer vers
nodenext(ciblage direct de Node.js) oubundler(bundlers/Bun)
Dépréciation des valeurs de module AMD, UMD et SystemJS
--module amd,--module umd,--module systemjset--module nonene sont plus pris en charge- ESM étant désormais largement pris en charge dans les navigateurs comme dans Node.js, il faut migrer vers un bundler ou vers une cible ESM
Dépréciation de --baseUrl
- Il était surtout utilisé comme préfixe pour
paths, mais agissait aussi comme racine de lookup pour la résolution de modules, ce qui pouvait provoquer des résolutions de chemins inattendues - La migration consiste à supprimer
baseUrlet à ajouter directement le préfixe dans les entréespaths- Exemple :
"@app/*": ["app/*"]→"@app/*": ["./src/app/*"]
- Exemple :
Dépréciation de --moduleResolution classic
- Il s’agit de l’algorithme de résolution de modules d’origine de TypeScript, mais tous les cas pratiques actuels peuvent être remplacés par
nodenextoubundler
Dépréciation de esModuleInterop false et allowSyntheticDefaultImports false
- Il devient impossible de mettre ces deux options à
false, ce qui signifie que le comportement d’interop sûr est toujours activé - Il peut donc être nécessaire d’ajuster
import * as express from "express"enimport express from "express"
Dépréciation de --alwaysStrict false
- Tout le code est désormais considéré en mode strict JavaScript, ce qui impose de renommer les identifiants comme
await,staticouprivatelorsqu’ils étaient utilisés comme noms ordinaires
Dépréciation de outFile
- Cette fonctionnalité permettait de fusionner plusieurs fichiers d’entrée en un seul, mais elle est désormais remplacée par des bundlers externes comme Webpack, Rollup, esbuild ou Vite
- La décision vise à recentrer TypeScript sur son rôle principal : le type checking et l’emit des déclarations
Dépréciation de l’ancienne syntaxe module (déclarations de namespace)
- La syntaxe
module Foo { ... }est dépréciée de manière stricte et doit être remplacée parnamespace Foo { ... } - Les déclarations de modules ambient sous la forme
declare module "some-module" { ... }restent prises en charge - L’objectif est d’éviter les conflits avec la proposition ECMAScript des blocs
module
Dépréciation du mot-clé d’import asserts
- Il faut remplacer
import ... asserts { type: "json" }parimport ... with { type: "json" } - Cette évolution suit le remplacement de la proposition d’import assertions par la proposition d’import attributes (mot-clé
with)
Dépréciation de la directive no-default-lib
/// <reference no-default-lib="true"/>n’est plus pris en charge ; il est recommandé d’utiliser--noLibou--libReplacement
Erreur lors de la spécification de fichiers en ligne de commande si tsconfig.json existe
- En exécutant
tsc foo.ts, une erreur est générée si untsconfig.jsonest présent dans le même répertoire - Il est possible de l’ignorer explicitement avec le flag
--ignoreConfig
Préparer TypeScript 7.0
- Les options dépréciées en 6.0 peuvent encore être utilisées sans erreur via le paramètre
"ignoreDeprecations": "6.0", mais elles seront entièrement supprimées dans la 7.0 - L’outil ts5to6 permet d’ajuster automatiquement
baseUrl,rootDir, etc. - TypeScript 7.0 devrait sortir dans les prochains mois et il est déjà largement adopté dans de très grosses bases de code, chez Microsoft comme à l’extérieur
- Les retours sont encouragés via les builds nightly de la preview native et l’extension VS Code
3 commentaires
J’ai hâte de voir le moment où la transition complète vers un compilateur basé sur Go aura lieu !
Hein ? TypeScript va être remplacé plus tard par une version native basée sur Go ?
Juste le compilateur