Le type Record de TypeScript, expliqué avec vos clés
Type Record de TypeScript
TypeScript Record<K, V> : objets de correspondance typés | We.Inc
Construisez un type Record<K, V> à partir de vos propres clés et voyez l'objet qu'il décrit. Découvrez quand Record est préférable à une signature d'index ou à une Map, et les erreurs qu'il détecte.
Record<K, V> est un type utilitaire intégré pour un objet dont les clés viennent de K et dont toutes les valeurs ont le type V. Donnez-lui une union de littéraux de chaîne et le compilateur exige que chaque clé listée soit présente. Donnez-lui simplement string et il se comporte comme un dictionnaire ouvert, comme une signature d'index.
Record en bref
Vous écrivez
Signifie
Clé manquante autorisée ?
Record<"a" | "b", number>
{ a: number; b: number }
Non, les deux clés sont requises
Record<string, number>
{ [key: string]: number }
Oui, n'importe quelle clé string
Partial<Record<"a" | "b", number>>
{ a?: number; b?: number }
Oui, chaque clé est optionnelle
Record<number, string>
{ [key: number]: string }
Oui, n'importe quelle clé number
Saisissez les clés voulues et choisissez un type de valeur. Le constructeur écrit le type Record, le type objet simple auquel il correspond et un objet de départ avec une ligne par clé, pour que vous voyiez exactement ce que le compilateur exigera avant de le coller dans votre code.
Saisissez vos clés séparées par des virgules, par exemple home, about, contact.
Choisissez le type de valeur que chaque clé doit contenir.
Cochez optionnel si certaines clés peuvent être omises, ce qui enveloppe le type dans Partial.
Copiez le type et l'objet de départ dans votre fichier et remplissez les valeurs.
Dérivez l'union de clés de données que vous avez déjà : keyof typeof someObject ou (typeof list)[number] après un tableau as const maintient le Record synchronisé avec la source.
N'utilisez Record<string, T> que lorsque les clés arrivent vraiment à l'exécution. Une union fermée attrape les fautes de frappe dans les noms de propriétés qu'un dictionnaire ouvert laisse passer.
Activez noUncheckedIndexedAccess si vous lisez un Record<string, T> avec une clé calculée. Les lectures renvoient alors T | undefined, ce qui correspond à ce qui se passe à l'exécution.
Évitez Record<string, any>. Record<string, unknown> accepte toujours n'importe quel objet mais impose une vérification avant d'utiliser une valeur.
Questions fréquentes
Record est-il identique à une signature d'index ?
Avec une clé large comme string, oui : Record<string, number> et { [key: string]: number } décrivent la même forme. La différence apparaît avec des clés littérales. Une signature d'index ne peut pas exiger que des noms précis existent, alors que Record<"a" | "b", number> exige à la fois a et b.
Quand utiliser une Map plutôt qu'un Record ?
Utilisez une Map quand les clés sont souvent ajoutées et supprimées, quand les clés ne sont pas des chaînes, ou quand vous avez besoin du nombre d'entrées via size. Utilisez un Record pour un ensemble fixe de noms, pour les objets de configuration et pour tout ce que vous passez à JSON.stringify.
Pourquoi TypeScript dit-il qu'une propriété manque dans mon Record ?
Parce que le type de clé est une union et que l'objet en omet un membre. tsc signale par exemple Property 'about' is missing in type '{ home: string; }'. Ajoutez la clé, ou enveloppez le type dans Partial si l'omettre est valide.
Record existe-t-il à l'exécution ?
Non. C'est uniquement un type, qui disparaît à la compilation. L'objet que vous créez est un objet JavaScript ordinaire, le compilateur ne peut donc pas empêcher une réponse serveur d'avoir des clés en trop ou manquantes.
Quelle version de TypeScript a ajouté Record ?
Record est arrivé dans TypeScript 2.1, avec Partial, Readonly et Pick, donc tout compilateur actuel le possède.
Comment Record est construit
Record est un mapped type. Il parcourt chaque membre du type de clé et donne à chacun le même type de valeur, c'est pourquoi Record<"a" | "b", number> correspond à un type objet avec deux propriétés number obligatoires.
Comme ce n'est qu'un type, vous pouvez lui passer tout ce qui peut servir de clé de propriété : littéraux de chaîne, number, string, symbol, ou une union de ceux-ci. Un type de clé construit à partir d'un autre type, comme keyof User, se met à jour tout seul quand User change.
Clés fermées ou clés ouvertes
Tout l'intérêt de Record est la forme fermée. Une table de correspondance de noms de routes, de libellés de statut ou de couleurs de thème typée avec une union de littéraux casse le build le jour où quelqu'un ajoute un nouveau statut sans libellé, c'est-à-dire exactement quand vous voulez en être averti.
La forme ouverte, Record<string, T>, décrit un dictionnaire. Elle ne dit rien des clés existantes, si bien que lire une clé donne T même quand la clé est absente. Associez-la à noUncheckedIndexedAccess ou à une Map quand ce manque compte.
Record, signature d'index ou Map
Choisissez Record avec des clés littérales pour les correspondances fixes, Record<string, T> ou une signature d'index pour les dictionnaires au format JSON, et Map pour les collections qui changent pendant l'exécution du programme. Le guide TypeScript Map de ce site traite ce dernier cas en détail.
Les modèles que vous utiliserez le plus
Clés issues d'un tableau as const
Le tableau est l'unique source de vérité. Ajoutez-y un statut et le compilateur signale la table de libellés jusqu'à ce que vous ajoutiez aussi le libellé.
Un indicateur par champ d'un autre type
keyof transforme un type existant en union de clés, l'objet d'état touched d'un formulaire liste donc toujours les mêmes champs que le formulaire.
Un dictionnaire ouvert, lu en toute sécurité
Avec noUncheckedIndexedAccess activé, une lecture par clé calculée donne number | undefined, la valeur de repli est donc obligatoire au lieu d'être oubliée.
Constructeur de type Record
Clés, séparées par des virgules
Type de valeur
Clés optionnelles (envelopper dans Partial)
Le type
Ce à quoi il correspond
Un objet de départ
Saisissez au moins une clé. Les clés doivent commencer par une lettre, _ ou $.