Microsoft annonce la disponibilité de TypeScript 5.7 Beta. Voici quelques mises à jour que TypeScript 5.7 apporte : vérification des variables jamais initialisées, réécriture de chemin pour les chemins relatifs, vérifications plus rapides de la propriété du projet dans les éditeurs pour les projets composites et d'autres changements notables.TypeScript est un langage de programmation de haut niveau, libre et gratuit, développé par Microsoft, qui ajoute à JavaScript un typage statique avec des annotations de type optionnelles. Il est conçu pour le développement de grandes applications et se transpose à JavaScript. Comme TypeScript est un surensemble de JavaScript, tous les programmes JavaScript sont syntaxiquement valides en TypeScript, mais ils peuvent ne pas vérifier le type pour des raisons de sécurité.
TypeScript 5.7 Beta est désormais disponible. À ce stade, TypeScript 5.7 serait "stable en termes de fonctionnalités". TypeScript 5.7 se concentrera sur les corrections de bogues, le polissage et certaines fonctionnalités d'édition à faible risque. Une version candidate sera disponible dans un peu plus d'un mois, suivie d'une version stable peu après.
Voici quelques mises à jour de cette version :
Vérification des variables jamais initialisées
Depuis longtemps, TypeScript est capable de détecter les problèmes lorsqu'une variable n'a pas encore été initialisée dans toutes les branches précédentes.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | let result: number
if (someCondition()) {
result = doSomeWork();
}
else {
let temporaryWork = doSomeWork();
temporaryWork *= 2;
// forgot to assign to 'result'
}
console.log(result); // error: Variable 'result' is used before being assigned. |
Malheureusement, dans certains cas, cette analyse ne fonctionne pas. Par exemple, si la variable est accédée dans une fonction séparée, le système de types ne sait pas quand la fonction sera appelée, et adopte une vue "optimiste" selon laquelle la variable sera initialisée.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function foo() {
let result: number
if (someCondition()) {
result = doSomeWork();
}
else {
let temporaryWork = doSomeWork();
temporaryWork *= 2;
// forgot to assign to 'result'
}
printResult();
function printResult() {
console.log(result); // no error here.
}
} |
Bien que TypeScript 5.7 soit encore indulgent envers les variables qui ont pu être initialisées, le système de types est capable de signaler des erreurs lorsque les variables n'ont jamais été initialisées du tout.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | function foo() {
let result: number
// do work, but forget to assign to 'result'
function printResult() {
console.log(result); // error: Variable 'result' is used before being assigned.
}
} |
Réécriture de chemin pour les chemins relatifs
Il existe plusieurs outils et moteurs d'exécution qui vous permettent d'exécuter du code TypeScript "sur place", ce qui signifie qu'ils ne nécessitent pas d'étape de compilation qui génère des fichiers JavaScript de sortie. Par exemple, ts-node, tsx, Deno et Bun permettent tous d'exécuter des fichiers .ts directement. Plus récemment, Node.js a étudié ce support avec --experimental-transform-types et --experimental-strip-types. C'est extrêmement pratique car cela permet d'itérer plus rapidement sans avoir à se soucier de relancer une tâche de construction.
Il y a cependant une certaine complexité à prendre en compte lors de l'utilisation de ces modes. Pour être compatible avec tous ces outils, un fichier TypeScript importé "sur-place" doit être importé avec l'extension TypeScript appropriée au moment de l'exécution. Par exemple, pour importer un fichier appelé foo.ts, nous devons écrire ce qui suit dans le nouveau support expérimental de Node :
| Code : | Sélectionner tout |
1 2 3 | // main.ts import * as foo from "./foo.ts"; // <- we need foo.ts here, not foo.js |
Typiquement, TypeScript émettrait une erreur si nous faisions cela, parce qu'il s'attend à ce que nous importions le fichier de sortie. Parce que certains outils autorisent les importations .ts, TypeScript a supporté ce style d'importation avec une option appelée --allowImportingTsExtensions depuis un certain temps. Cela fonctionne bien, mais que se passe-t-il si nous avons besoin de générer des fichiers .js à partir de ces fichiers .ts ? C'est une exigence pour les auteurs de bibliothèques qui devront être en mesure de distribuer uniquement des fichiers .js, mais jusqu'à présent TypeScript a évité de réécrire les chemins.
Pour supporter ce scénario, cette version apporte une nouvelle option de compilation appelée --rewriteRelativeImportExtensions. Lorsqu'un chemin d'importation est relatif (commence par ./ ou ../), se termine par une extension TypeScript (.ts, .tsx, .mts, .cts), et est un fichier sans déclaration, le compilateur réécrira le chemin vers l'extension JavaScript correspondante (.js, .jsx, .mjs, .cjs).
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | // Under --rewriteRelativeImportExtensions... // these will be rewritten. import * as foo from "./foo.ts"; import * as bar from "../someFolder/bar.mts"; // these will NOT be rewritten in any way. import * as a from "./foo"; import * as b from "some-package/file.ts"; import * as c from "@some-scope/some-package/file.ts"; import * as d from "#/file.ts"; import * as e from "./file.js"; |
Cela permet d'écrire du code TypeScript qui peut être exécuté sur place, puis compilé en JavaScript.
TypeScript évitait généralement de réécrire les chemins. Il y a plusieurs raisons à cela, mais la plus évidente est l'importation dynamique. Si un développeur écrit ce qui suit, il n'est pas négligeable de gérer le chemin que import reçoit. En fait, il est impossible de remplacer le comportement de import dans les dépendances.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | function getPath() {
if (Math.random() < 0.5) {
return "./foo.ts";
}
else {
return "./foo.js";
}
}
let myImport = await import(getPath()); |
Un autre problème est que seuls les chemins "relatifs" sont réécrits, et ils sont écrits "naïvement". Cela signifie que tout chemin qui s'appuie sur baseUrl et path de TypeScript ne sera pas réécrit :
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | // tsconfig.json
{
"compilerOptions": {
"module": "nodenext",
// ...
"paths": {
"@/*": ["./src/*"]
}
}
} |
| Code : | Sélectionner tout |
1 2 | // Won't be transformed, won't work. import * as utilities from "@/utilities.ts"; |
Il en va de même pour tout chemin qui pourrait être résolu par les champs exports et imports d'un package.json.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 | // package.json
{
"name": "my-package",
"imports": {
"#root/*": "./dist/*"
}
} |
| Code : | Sélectionner tout |
1 2 | // Won't be transformed, won't work. import * as utilities from "#root/utilities.ts"; |
Par conséquent, si vous avez utilisé une disposition de type espace de travail avec plusieurs paquets se référençant les uns les autres, vous devrez peut-être utiliser des exportations conditionnelles avec des conditions personnalisées à portée pour que cela fonctionne :
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // my-package/package.json
{
"name": "my-package",
"exports": {
".": {
"@my-package/development": "./src/index.ts",
"import": "./lib/index.js"
},
"./*": {
"@my-package/development": "./src/*.ts",
"import": "./lib/*.js"
}
}
} |
Chaque fois que vous voulez importer les fichiers .ts, vous pouvez l'exécuter avec node --conditions=...
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.