Microsoft est heureux d'annoncer la Release Candidate (RC) de TypeScript 5.1 ! D'ici la sortie de la version stable de TypeScript 5.1, il ne devrait pas y avoir d'autres changements hormis des corrections de bogues critiques.Pour commencer à utiliser la RC, vous pouvez l'obtenir via NuGet, ou via npm avec la commande suivante :
| Code : | Sélectionner tout |
npm install -D typescript@rc
[QUOTE]Quoi de neuf depuis la bêta ?
Depuis la bêta, nous avons corrigé certains de nos comportements pour les crochets init dans les décorateurs, car le comportement proposé a été ajusté. Nous avons également modifié le comportement d'emit sous isolatedModules, en nous assurant que les fichiers de scripts ne sont pas réécrits en modules. Cela signifie également que l'utilisation de l'API transpileModule garantira également que les fichiers de script ne sont pas interprétés comme des modules, car elle suppose l'utilisation d'isolatedModules.
En plus de ces changements, nous avons récemment ajouté un nouveau support de refactoring pour déplacer les déclarations vers des fichiers existants.
Retours implicites plus faciles pour les fonctions avec retour undefined
En JavaScript, si une fonction s'exécute sans return, elle renvoie la valeur undefined.
| Code : | Sélectionner tout |
1 2 3 4 5 6 | function foo() {
// no return
}
// x = undefined
let x = foo(); |
Cependant, dans les versions précédentes de TypeScript, les seules fonctions qui ne pouvaient avoir aucune instruction de retour étaient les fonctions qui retournaient void et any. Cela signifiait que même si vous disiez explicitement "cette fonction renvoie une valeur undefined", vous étiez obligé d'avoir au moins une instruction de retour.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // fine - we inferred that 'f1' returns 'void'
function f1() {
// no returns
}
// fine - 'void' doesn't need a return statement
function f2(): void {
// no returns
}
// fine - 'any' doesn't need a return statement
function f3(): any {
// no returns
}
// error!
// A function whose declared type is neither 'void' nor 'any' must return a value.
function f4(): undefined {
// no returns
} |
Cela peut s'avérer gênant si une API attend d'une fonction qu'elle renvoie une valeur undefined. Il faut alors soit un retour explicite de la valeur undefined, soit une déclaration return et une annotation explicite.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | declare function takesFunction(f: () => undefined): undefined;
// error!
// Argument of type '() => void' is not assignable to parameter of type '() => undefined'.
takesFunction(() => {
// no returns
});
// error!
// A function whose declared type is neither 'void' nor 'any' must return a value.
takesFunction((): undefined => {
// no returns
});
// error!
// Argument of type '() => void' is not assignable to parameter of type '() => undefined'.
takesFunction(() => {
return;
});
// works
takesFunction(() => {
return undefined;
});
// works
takesFunction((): undefined => {
return;
}); |
Ce comportement était frustrant et déroutant, en particulier lors de l'appel de fonctions échappant au contrôle de l'utilisateur. Comprendre l'interaction entre l'inférence de void sur undefined, si une fonction à retour undefined a besoin d'une déclaration return, etc. semble être une distraction.
Tout d'abord, TypeScript 5.1 permet désormais aux fonctions à retour undefined de ne pas avoir de déclaration de retour.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | // Works in TypeScript 5.1!
function f4(): undefined {
// no returns
}
// Works in TypeScript 5.1!
takesFunction((): undefined => {
// no returns
}); |
Deuxièmement, si une fonction n'a pas d'expression de retour et qu'elle est passée à quelque chose qui attend une fonction qui retourne undefined, TypeScript déduit undefined pour le type de retour de cette fonction.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Works in TypeScript 5.1!
takesFunction(function f() {
// ^ return type is undefined
// no returns
});
// Works in TypeScript 5.1!
takesFunction(function f() {
// ^ return type is undefined
return;
}); |
Pour résoudre un autre problème similaire, avec l'option --noImplicitReturns de TypeScript, les fonctions retournant uniquement undefined bénéficient désormais d'une exception similaire à void, en ce sens que chaque chemin de code ne doit pas se terminer par un return explicite.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 | // Works in TypeScript 5.1 under '--noImplicitReturns'!
function f(): undefined {
if (Math.random()) {
// do some stuff...
return;
}
} |
TypeScript 4.3 permet de dire qu'une paire d'accesseurs get et set peut spécifier deux types différents.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | interface Serializer {
set value(v: string | number | boolean);
get value(): string;
}
declare let box: Serializer;
// Allows writing a 'boolean'
box.value = true;
// Comes out as a 'string'
console.log(box.value.toUpperCase()); |
Initialement, nous exigions que le type get soit un sous-type du type set. Cela signifiait que l'écriture de
| Code : | Sélectionner tout |
box.value = box.value;
Cependant, il existe de nombreuses API existantes et proposées qui ont des types complètement différents entre leurs getters et setters. Prenons l'un des exemples les plus courants : la propriété style dans le DOM et l'API CSSStyleRule. Chaque règle de style possède une propriété de style qui est une CSSStyleDeclaration ; cependant, si vous essayez d'écrire dans cette propriété, elle ne fonctionnera correctement qu'avec une chaîne de caractères !
TypeScript 5.1 autorise désormais des types totalement indépendants pour les propriétés d'accès get et set, à condition qu'elles aient des annotations de type explicites. Et bien que cette version de TypeScript ne modifie pas encore les types de ces interfaces intégrées, CSSStyleRule peut désormais être défini de la manière suivante :
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | interface CSSStyleRule {
// ...
/** Always reads as a `CSSStyleDeclaration` */
get style(): CSSStyleDeclaration;
/** Can only write a `string` here. */
set style(newValue: string);
// ...
} |
Cela permet également d'autres modèles, comme le fait d'exiger que les accesseurs set n'acceptent que des données "valides", tout en spécifiant que les accesseurs get peuvent renvoyer undefined si un état sous-jacent n'a pas encore été initialisé.
| Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | class SafeBox {
#value: string | undefined;
// Only accepts strings!
set value(newValue: string) {
}
// Must check for 'undefined'!
get value(): string | undefined {
return this.#value;
}
} |
En fait, ceci est similaire à la façon dont les propriétés optionnelles sont vérifiées sous --exactOptionalProperties.
Vérification de type découplée entre les éléments JSX et les types de balises JSX
L'un des points problématiques de TypeScript avec JSX était ses exigences sur le type de chaque balise de l'élément JSX.
Pour le contexte, un élément JSX est l'un ou l'autre des éléments suivants :
| Code : | Sélectionner tout |
1 2 3 4 5 | // A self-closing JSX tag <Foo /> // A regular element with an opening/closing tag <Bar></Bar> |
Lors de la vérification du type <Foo /> ou <Bar></Bar>, TypeScript recherche toujours un espace de noms appelé JSX et en extrait un type appelé Element - ou plus directement, il recherche JSX.Element.
Mais pour vérifier si Foo ou Bar sont valides pour être utilisés comme noms de balises, TypeScript se contente de récupérer les types renvoyés ou construits par Foo ou Bar et vérifie leur compatibilité avec JSX.Element (ou un autre type appelé JSX.ElementClass si le type est constructible).
Les limitations ici signifiaient que les composants ne pouvaient pas être utilisés s'ils renvoyaient ou "rendaient" un type plus large que JSX.Element. Par exemple, une bibliothèque JSX pourrait s'accommoder d'un composant renvoyant strings ou Promises.
Pour donner un exemple plus concret, React envisage d'ajouter un support limité pour les composants qui renvoient Promises, mais les versions existantes de TypeScript ne peuvent pas l'exprimer sans que...
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.