Historique de la question
TypeScript a été développé dès le départ pour un typage strict des objets et l'écriture d'un code JavaScript plus prévisible. L'un des outils pour garantir la sécurité lors de l'accès aux propriétés des objets est l'opérateur keyof, qui est apparu dans TypeScript 2.1. Il permet de créer des types représentant un ensemble de clés de chaîne (et symboliques) disponibles dans le type d'objet déclaré.
Problème
En JavaScript pur, les propriétés d'un objet peuvent être interrogées par n'importe quelle chaîne, et si une erreur se produit, on obtient undefined ou une erreur qui ne sera trouvée qu'à l'exécution. Sans typage strict, il est facile de faire une faute de frappe ou d'oublier de mettre à jour la chaîne clé lors du refactoring. De plus, il est souvent nécessaire de construire une fonction qui n'accepte que des clés valides d'un objet ou type spécifique.
Solution
L'opérateur keyof crée un type union à partir de toutes les clés du type. Il permet de limiter les clés valides, d'augmenter la sécurité des API (par exemple, pour les fonctions getter/setter) et de créer des types utilitaires génériques.
Exemple de code :
type User = { name: string; age: number; active: boolean }; type UserKey = keyof User; // "name" | "age" | "active" function getProp<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const user: User = { name: 'Tom', age: 33, active: true }; const age = getProp(user, 'age'); // l'âge est de type number
Caractéristiques clés :
Que renvoie keyof pour un tableau et peut-on obtenir des index ?
keyof pour un tableau renvoie les types de clés d'objet, que le tableau est en fait dans JS. Ce sont généralement des chaînes d'index et des propriétés spéciales du tableau.
Exemple de code :
type A = keyof number[]; // "length" | "toString" | "pop" | ... | number
keyof peut-il retourner des clés pour des types union ?
Oui, keyof d'un type union renvoie l'intersection des clés des deux objets, et non leur union.
Exemple de code :
type A = {a: string, b: number } type B = {b: number, c: boolean } type C = keyof (A | B); // "b"
Que se passe-t-il si la propriété d'un objet est optionnelle ? L'opérateur keyof prend-il en charge "?" ?
Oui, les propriétés optionnelles font également partie du type de clé résultant, mais cela ne signifie pas que la propriété est forcément présente sur l'objet à l'exécution.
Exemple de code :
type D = { a: string; b?: number }; type DK = keyof D; // "a" | "b"
On écrit une fonction getProperty(obj, key) avec une clé de type chaîne, on appelle avec une clé inexistante — l'erreur n'apparaît qu'à l'exécution.
Avantages :
Inconvénients :
On utilise des génériques : getProperty<T, K extends keyof T>(), le type key est strictement limité aux clés de la structure.
Avantages :
Inconvénients :