L'opérateur keyof de TypeScript est un moyen utile d'interroger les noms de propriétés d'un type existant.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 | interface Person { name: string; age: number; } // Equivalent to the type // "name" | "age" type PersonPropertiesNames = keyof Person; |
Cependant, parce que keyofest antérieur à la capacité de TypeScript de raisonner sur des types de symboles uniques, keyof n'a jamais reconnu les clés symboliques.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | const baz = Symbol("baz"); interface Thing { foo: string; bar: number; [baz]: boolean; // this is a computed property type } // Error in TypeScript 2.8 and earlier! // `typeof baz` isn't assignable to `"foo" | "bar"` let x: keyof Thing = baz; |
TypeScript 2.9 modifie le comportement de keyof afin qu’il prenne en compte à la fois les symboles uniques et les types littéraux numériques. En tant que tel, l'exemple ci-dessus se compile maintenant comme prévu. keyof Thing se résume maintenant au type "foo" | "bar" | typeof baz.
Avec cette fonctionnalité, les types d'objets mappés comme Partial, Required ou Readonly reconnaissent également les clés de propriétés symboliques et numériques et ne suppriment plus les propriétés nommées par des symboles:
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | type Partial<T> = { [K in keyof T]: T[K] } interface Thing { foo: string; bar: number; [baz]: boolean; } type PartialThing = Partial<Thing>; // This now works correctly and is equivalent to // // interface PartialThing { // foo?: string; // bar?: number; // [baz]?: boolean; // } |
Malheureusement, il s'agit d'un changement radical pour toute utilisation où les utilisateurs pensaient que pour tout type T, keyof T serait toujours assignable à une chaîne. Comme les propriétés nommées par des symboles et des nombres invalident cette hypothèse, Microsoft s’attend à des ruptures mineures qu’elle pense faciles à attraper. Dans ce cas, plusieurs solutions de contournement sont possibles.
Si vous avez du code qui ne doit fonctionner que sur les propriétés d'une chaîne, vous pouvez utiliser Extract <keyof T, string> pour limiter les entrées de symboles et de nombres:
Code TypeScript : | Sélectionner tout |
1 2 3 4 | function useKey<T, K extends Extract<keyof T, string>>(obj: T, k: K) { let propName: string = k; // ... } |
Si vous avez du code plus largement applicable et que vous pouvez gérer plus que des chaînes, vous devriez pouvoir remplacer string par string | number | symbol, ou utilisez l'alias de type intégré PropertyKey.
[CODE)TypeScript]function useKey<T, K extends keyof T>(obj: T, k: K) {
let propName: string | number | symbol = k;
// ...
}[/CODE]
Alternativement, les utilisateurs peuvent revenir à l'ancien comportement sous l'indicateur de compilation --keyofStringsOnly mais ceci est destiné à être utilisé comme un drapeau de transition.
types import ()
L’une des difficultés rencontrées dans TypeScript a été l'impossibilité de référencer un type dans un autre module, ou le type du module lui-même, sans inclure une importation en haut du fichier.
Dans certains cas, il s'agit simplement d'une question de commodité - vous ne voudrez peut-être pas ajouter une importation en haut de votre fichier pour décrire l'utilisation d'un seul type. Par exemple, pour référencer le type d'un module à un emplacement arbitraire, voici ce que vous deviez écrire avant TypeScript 2.9:
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 | import * as _foo from "foo"; export async function bar() { let foo: typeof _foo = await import("foo"); } |
Dans d'autres cas, il y a simplement des choses que les utilisateurs ne peuvent pas réaliser aujourd'hui - par exemple, référencer un type dans un module dans la portée globale est impossible aujourd'hui. En effet, un fichier avec des imports ou des exports est considéré comme un module, donc ajouter un import pour un type dans un fichier script global transformera automatiquement ce fichier en module, ce qui change drastiquement les choses comme les règles de portée et le module strict.
C'est pourquoi TypeScript 2.9 introduit la nouvelle syntaxe de type import (...). Tout comme les expressions import (...) proposées par ECMAScript, les types d'importation utilisent la même syntaxe et fournissent un moyen pratique de référencer le type d'un module ou les types qu'il contient.
Code TypeScript : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | // foo.ts export interface Person { name: string; age: number; } // bar.ts export function greet(p: import("./foo").Person) { return ` Hello, I'm ${p.name}, and I'm ${p.age} years old. `; } |
Source : blog Microsoft
Et vous ?
Quels sont les changements qui vous intéressent le plus ?
Voir aussi :
TypeScript 2.8 est disponible et s'accompagne des types conditionnels, ainsi que du contrôle granulaire sur les modificateurs de type mappés
Microsoft annonce la disponibilité de la version stable de TypeScript 2.7, qui s'accompagne de contrôles de propriété de classe plus stricts
TypeScript entre dans le top 20 des langages les plus populaires, d'après le classement Redmonk de juin 2017
La RC de TypeScript 2.7 est disponible et s'accompagne de la vérification d'attribution définie pour les propriétés de classe