Microsoft annonce la disponibilité de TypeScript 2.8 qui s'accompagne des types conditionnels,
et de contrôle granulaire sur les modificateurs de type mappés
Microsoft a annoncé la disponibilité de TypeScript 2.8.
Types conditionnels
Les types conditionnels sont une nouvelle construction dans TypeScript qui permette de choisir des types basés sur d'autres types. Ils prennent la forme
A extends B ? C : D
où A, B, C et D sont tous les types. Vous devriez lire cela comme étant «quand le type A est assignable à B, alors ce type est C; sinon, c'est D». Ceux qui ont déjà utilisé la syntaxe conditionnelle dans d’autres langages comme JavaScript vont probablement très vite retrouver leurs repères.
Prenons un exemple spécifique:
interface Animal {
live(): void;
}
interface Dog extends Animal {
woof(): void;
}
// Has type 'number'
type Foo = Dog extends Animal ? number : string;
// Has type 'string'
type Bar = RegExp extends Dog ? number : string;
Vous pourriez vous demander pourquoi cela est immédiatement utile. Nous pouvons dire que Foo sera un nombre, et Bar sera une chaîne, donc nous pourrions aussi bien l'écrire explicitement. Mais le vrai pouvoir des types conditionnels vient de leur utilisation avec des génériques.
Par exemple, prenons la fonction suivante:
interface Id { id: number, /* other fields */ }
interface Name { name: string, /* other fields */ }
declare function createLabel(id: number): Id;
declare function createLabel(name: string): Name;
declare function createLabel(name: string | number): Id | Name;
Ces surcharges pour createLabel décrivent une seule fonction JavaScript qui fait un choix en fonction des types de ses entrées. Notez deux choses:
Au lieu de cela, nous pouvons utiliser un type conditionnel pour réduire à la fois nos surcharges et créer un alias de type afin que nous puissions réutiliser cette logique.
type IdOrName
T extends number ? Id : Name;
declare function createLabel
T extends number ? Id : Name;
let a = createLabel("typescript"); // Name
let b = createLabel(2.8); // Id
let c = createLabel("" as any); // Id | Name
let d = createLabel("" as never); // never
Tout comme la façon dont JavaScript peut prendre des décisions au moment de l'exécution en fonction des caractéristiques d'une valeur, les types conditionnels permettent à TypeScript de prendre des décisions dans le système de types en fonction des caractéristiques des autres types.
Distribution sur les unions avec les types conditionnels
Lorsque les types conditionnels agissent sur un seul paramètre de type, ils se répartissent entre les unions. Donc, dans l'exemple suivant, Bar a le type string [] | number [] car Foo est appliqué à l’union type string | number
type Foo
/**
* Foo distributes on 'string | number' to the type
*
* (string extends any ? string[] : never) |
* (number extends any ? number[] : never)
*
* which boils down to
*
* string[] | number[]
*/
type Bar = Foo
Au cas où vous deviez éviter de distribuer sur des unions, vous pouvez entourer chaque côté du mot-clé extends avec des crochets:
type Foo
// Boils down to Array
type Bar = Foo

Contrôle granulaire sur les modificateurs de type mappés
Les types d'objets mappés de TypeScript sont une construction incroyablement puissante. Une fonctionnalité pratique est qu'ils permettent aux utilisateurs de créer de nouveaux types avec des modificateurs définis pour toutes leurs propriétés. Par exemple, le type suivant crée un nouveau type basé sur T et où chaque propriété dans T devient readonly et optionnel (?).
// Creates a type with all the properties in T,
// but marked both readonly and optional.
type ReadonlyAndPartial
readonly [P in keyof T]?: T
}
Les types d'objets mappés peuvent donc ajouter des modificateurs, mais jusqu'à présent, il n'y avait aucun moyen de supprimer les modificateurs de T.
TypeScript 2.8 fournit une nouvelle syntaxe pour supprimer les modificateurs dans les types mappés avec l'opérateur -, et une nouvelle syntaxe plus explicite pour ajouter des modificateurs avec l'opérateur +. Par exemple:
type Mutable
-readonly [P in keyof T]: T
}
interface Foo {
readonly abc: number;
def?: string;
}
// 'abc' is no longer read-only, but 'def' is still optional.
type TotallyMutableFoo = Mutable
Dans ce qui précède, Mutable supprime readonly de chaque propriété du type sur lequel elle est mappée.
De même, TypeScript fournit maintenant un nouveau type requis dans lib.d.ts qui supprime l'optionalité de chaque propriété:
/**
* Make all properties in T required
*/
type Required
[P in keyof T]-?: T;
}
L'opérateur + peut être utile lorsque vous voulez rappeler qu'un type mappé ajoute des modificateurs. Par exemple, notre ReadonlyAndPartial de ci-dessus pourrait être défini comme suit:
type ReadonlyAndPartial
+readonly [P in keyof T]+?: T;
}
Source: Microsoft
Et vous?
:fleche: Quels sont les changements qui vous intéressent le plus?
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.