Microsoft annonce la disponibilité de TypeScript 2.4
TypeScript 2.4 est disponible en Release Candidate
et s'accompagne des expressions d'importation dynamique
Expressions d'importation dynamique
TypeScript 2.4 prend en charge les appels new Import () de ECMAScript. Ces appels importent un module et renvoient un Promise (une classe dont la motivation principale est d'apporter la gestion des erreurs de style synchrone au code de style Async / Callback.) à ce module.
Par exemple, imaginez une page Web qui vous permet de créer et d'éditer des images. Lorsque vous travaillez avec un fichier, la page vous permettra de télécharger immédiatement ce fichier. Mais si vous travaillez sur plusieurs images, vous pouvez les enregistrer en tant que fichier .zip.
Vous pourriez avoir une bibliothèque d'utilité pour créer un fichier zip, mais comme le téléchargement de plusieurs fichiers n'est pas si courant, vous voudrez charger cette fonctionnalité paresseusement. Les expressions import () vous permettent de charger un module à la volée en tant que Promise comme suit
Code:
1 2 3 4 5
| async function getZipFile(name: string, files: File[]): Promise<File> {
const zipUtil = await import('./utils/create-zip-file');
const zipContents = await zipUtil.getContentAsBlob(files);
return new File(zipContents, name);
} |
Microsoft assure que cette fonctionnalité peut s’avérer incroyablement utile dans les situations où vous souhaitez importer des modules conditionnellement. Les projets qui utilisent des groupes comme Webpack peuvent fonctionner sur ces appels import () et diviser le code en petits paquets qui peuvent être chargés en peu de temps.
Ce que tout cela signifie est que :
- vous pouvez envoyer moins de JS sur le fil pour des scénarios plus courants ;
- vos utilisateurs peuvent obtenir des temps de chargement de page plus rapides pour du contenu critique.
Une vérification de paramètres de rappel plus sûr
Lorsque vous vérifiez si deux fonctions sont assignables l'une à l'autre, TypeScript vérifie si leurs paramètres sont bidirectionnellement assignables : Microsoft l’appelle bivariance de paramètres de fonction. Il y a plusieurs raisons à cela, mais elles découlent principalement du caractère structurel de TypeScript et de la façon dont Microsoft a essayé de faire correspondre l'intuition des gens.
D’après son expérience, les utilisateurs ne se heurtent généralement pas à des problèmes avec tout cela. Cependant, Microsoft a observé que ce modèle s'effondre face à des conteneurs qui ont transmis des données internes via des rappels – en particulier des Promises. Par exemple, Promise <Animal> était assignable à Promise <Chien>, ce qui est incorrect. Vous pouvez voir un comportement similaire dans l'exemple suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| interface Animal { animalStuff: any }
interface Dog extends Animal { bark(): void }
interface BasicCollection<T> {
forEach(callback: (value: T) => void): void;
}
declare let animalCollection: BasicCollection<Animal>;
declare let dogCollection: BasicCollection<Dog>;
// Ceci devrait être une erreur, mais jusquà TypeScript 2.3, le langage le permet
.
dogCollection = animalCollection; |
Pour résoudre ce problème, TypeScript 2.4 resserre désormais les choses et compare les paramètres qui sont notamment les rappels. Lors de la vérification des rappels, TypeScript sera strict quant à la vérification des paramètres de façon contravariante par rapport à la vérification actuelle. La bivarité des paramètres s'applique toujours autrement, mais Microsoft a constaté que c'était une vérification de sécurité efficace sans changer radicalement le système de type.
Types faibles
Dans TypeScript 1.6, Microsoft avait ajouté une vérification des propriétés excédentaires dans les littéraux d'objets. Cette vérification a cherché des propriétés inattendues dans les littéraux d'objets, et il est arrivé qu’elle attrape une grande classe de bogues. La seule lacune du contrôle était que si vous n'avez pas immédiatement transmis votre objet littéraire à quelque chose du type approprié, le contrôle ne serait pas déclenché.
Dans TypeScript 2.4, Microsoft ajoute une vérification similaire pour ce qu’elle appelle les types faibles. Tout type qui contient uniquement des propriétés facultatives est considéré comme un type faible puisqu'il offre peu de restrictions sur ce qui peut lui être attribué. Par exemple, ce type d'options est un type faible :
Code:
1 2 3 4 5
| interface Options {
data?: string,
timeout?: number,
maxRetries?: number,
} |
Dans TypeScript 2.4, il est maintenant une erreur d'attribuer n'importe quoi à un type faible lorsqu'il n'y a pas de chevauchement dans les propriétés. Par exemple :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function sendMessage(options: Options) {
// ...
}
const opts = {
payload: "hello world!",
retryOnFail: true,
}
// Error!
sendMessage(opts);
// No overlap between the type of 'opts' and 'Options' itself.
// Maybe we meant to use 'data'/'maxRetries' instead of 'payload'/'retryOnFail' |
Étant donné qu'il s'agit d'un changement qui peut provoquer une rupture, vous devrez peut-être connaître les solutions de rechange identiques à celles des contrôles stricts de l'objet :
Déclarez les propriétés si elles existent réellement.
Ajoutez une signature d'index au type faible (c'est-à-dire [propName: string]: {}).
Utilisez une assertion de type (c'est-à-dire opts as Options).
Source : Microsoft
Microsoft annonce la disponibilité de TypeScript 2.4
Microsoft annonce la disponibilité de TypeScript 2.4
qui apporte une vérification plus stricte des paramètres de retour
Expressions dynamiques import ()
Les expressions d'importation dynamique sont une nouvelle fonctionnalité dans ECMAScript qui vous permet de demander de manière asynchrone un module à n'importe quel point arbitraire dans votre programme. Ces modules reviennent en tant que Promises (transformation d'une fonction asynchrone en un objet – au sens JavaScript du terme – afin de faciliter la manipulation de ladite fonction asynchrone) du module lui-même, et peuvent être en mode await dans une fonction asynchrone, ou peuvent recevoir un rappel avec .then.
Ce que cela signifie, en bref, est que vous pouvez importer de façon conditionnelle et paresseuse d'autres modules et bibliothèques pour rendre votre application plus efficace et plus soucieuse des ressources. Par exemple, voici une fonction async qui n'importe qu'une bibliothèque d'utilitaires lorsqu'elle est nécessaire :
Code:
1 2 3 4 5
| async function getZipFile(name: string, files: File[]): Promise<File> {
const zipUtil = await import('./utils/create-zip-file');
const zipContents = await zipUtil.getAsBlob(files);
return new File(zipContents, name);
} |
Microsoft indique que nombreux sont les bundlers qui disposent d’un support pour diviser automatiquement les lots de sortie (ou encore le « fractionnement de code ») en fonction de ces expressions import (), alors les ingénieurs proposent d’envisager d'utiliser cette nouvelle fonctionnalité avec la cible module esnext. Notez que cette fonctionnalité ne sera pas effective avec la cible module es2015, car la fonctionnalité est prévue pour ES2018 ou une version ultérieure.
Énumération de chaînes de caractères
Cela fait déjà un moment que TypeScript dispose des types de chaînes littérales, et d’enums depuis sa sortie. Ayant eu le temps de voir comment ces fonctionnalités étaient utilisées, les ingénieurs ont modifié les énumérations dans TypeScript 2.4 pour voir comment ils pourraient travailler ensemble. Cette version de TypeScript permet maintenant aux membres d'énumération de contenir des initialiseurs de chaînes.
Code:
1 2 3 4 5
| enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
} |
Les énumérations de chaînes de caractères ont l'avantage d’être beaucoup plus faciles à déboguer et peuvent également décrire les systèmes existants qui utilisent des chaînes. Comme les énumérations numériques et les types littéraires, ces énumérations peuvent également être utilisées comme étiquettes dans des unions discriminées.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| enum ShapeKind {
Circle = "circle",
Square = "square"
}
interface Circle {
kind: ShapeKind.Circle;
radius: number;
}
interface Square {
kind: ShapeKind.Square;
sideLength: number;
}
type Shape = Circle | Square; |
Vérification améliorée des génériques
TypeScript 2.4 comporte des améliorations dans la façon dont les types sont déduits lorsque les génériques entrent en jeu, ainsi qu'une vérification améliorée lors de la relation entre deux types de fonctions génériques.
Types de retour comme cibles d'inférence
TypeScript peut désormais permettre aux types de fluctuer à travers les types de retour dans certains contextes. Cela signifie que vous pouvez décider plus facilement où placer vos types. Par exemple :
Code:
1 2 3 4 5
| function arrayMap<T, U>(f: (x: T) => U): (a: T[]) => U[] {
return a => a.map(f);
}
const lengths: (a: string[]) => number[] = arrayMap(s => s.length); |
Il arrivait que "s" ait besoin d'être explicitement annoté ou son type aurait été déduit comme {}. Bien que les longueurs puissent être laissées sans description dans ce cas, il a été surprenant pour certains utilisateurs que l'information de ce type n'ait pas été utilisée pour déduire le type de s.
Dans TypeScript 2.4, le système de type sait que "s" est une chaîne du type de longueurs, ce qui pourrait mieux répondre à vos choix stylistiques.
Cela signifie également que certaines erreurs seront détectées, puisque TypeScript peut trouver de meilleurs candidats que le type {} par défaut (ce qui est souvent trop permissif).
Code:
1 2 3 4
| let x: Promise<string> = new Promise(resolve => {
resolve(10);
// ~~ Now correctly errors!
}); |
Vérification plus stricte des fonctions génériques
TypeScript essaie maintenant d'unifier les paramètres de type lors de la comparaison de deux types de signature unique. En conséquence, vous obtiendrez des contrôles plus stricts lors de la relation entre deux signatures génériques qui peuvent détecter certains bogues.
Code:
1 2 3 4 5 6 7
| type A = <T, U>(x: T, y: U) => [T, U];
type B = <S>(x: S, y: S) => [S, S];
function f(a: A, b: B) {
a = b; // Error
b = a; // Ok
} |
Une vérification de paramètres de rappel plus sûr
Lorsque vous vérifiez si deux fonctions sont assignables l'une à l'autre, TypeScript vérifie si leurs paramètres sont bidirectionnellement assignables : Microsoft l’appelle bivariance de paramètres de fonction. Il y a plusieurs raisons à cela, mais elles découlent principalement du caractère structurel de TypeScript et de la façon dont Microsoft a essayé de faire correspondre l'intuition des gens.
D’après son expérience, les utilisateurs ne se heurtent généralement pas à des problèmes avec tout cela. Cependant, Microsoft a observé que ce modèle s'effondre face à des conteneurs qui ont transmis des données internes via des rappels – en particulier des Promises. Par exemple, Promise <Animal> était assignable à Promise <Chien>, ce qui est incorrect. Vous pouvez voir un comportement similaire dans l'exemple suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
| interface Animal { animalStuff: any }
interface Dog extends Animal { bark(): void }
interface BasicCollection<T> {
forEach(callback: (value: T) => void): void;
}
declare let animalCollection: BasicCollection<Animal>;
declare let dogCollection: BasicCollection<Dog>;
// Ceci devrait être une erreur, mais jusquà TypeScript 2.3, le langage le permet
.
dogCollection = animalCollection; |
Pour résoudre ce problème, TypeScript 2.4 resserre désormais les choses et compare les paramètres qui sont notamment les rappels. Lors de la vérification des rappels, TypeScript sera strict quant à la vérification des paramètres de façon contravariante par rapport à la vérification actuelle. La bivarité des paramètres s'applique toujours autrement, mais Microsoft a constaté que c'était une vérification de sécurité efficace sans changer radicalement le système de type.
Source : Microsoft
Et vous ?
:fleche: Quelles fonctionnalités vous intéressent le plus ?
Voir aussi :
:fleche: Comprendre les Promises en JavaScript / TypeScript, article de yahiko
:fleche: TypeScript entre dans le top 20 des langages les plus populaires, d'après le classement Redmonk de juin 2017
:fleche: Après avoir réécrit Angular en TypeScript, Google approuve le surensemble JavaScript de Microsoft pour ses développements internes