Record en TypeScript : on passe à la pratique
\n\nImaginez que vous développez une application pour apprendre le vocabulaire anglais. Vous devez stocker des traductions : cat → chat, dog → chien. Comment typer cela correctement en TypeScript ? Vous pourriez créer une interface, mais que faire si les clés sont inconnues à l'avance ? Ou si elles sont trop nombreuses ? C'est là qu'intervient Record — l'un des types utilitaires les plus utiles, mais souvent sous-estimés.
Dans cet article, nous allons voir ce qu'est le type Record en TypeScript, avec des exemples concrets que vous pourrez appliquer immédiatement dans vos projets. Pas de théorie ennuyeuse, que de la pratique.
\n\nQu'est-ce que Record en TypeScript ? Explication simple
\n\nRecord<K, V> est un type utilitaire intégré qui crée un objet dont toutes les clés sont de type K et toutes les valeurs de type V.
Considérez-le comme un dictionnaire typé ou une map avec un ensemble de clés fixes.
La syntaxe de base est la suivante :
\n\n// Un objet classique\nconst userRoles: Record<string, string> = {\n admin: 'Administrateur',\n user: 'Utilisateur',\n guest: 'Invité'\n};\n\nIci, Record<string, string> signifie : « Un objet dont les clés sont des chaînes et les valeurs sont aussi des chaînes ». Simple et clair.
Pourquoi Record est-il meilleur qu'une interface classique ?
\n\n- \n
- Flexibilité des clés : Vous pouvez définir un ensemble spécifique de clés via un type union. \n
- Concision : Pas besoin de décrire chaque champ manuellement. \n
- Sécurité : TypeScript vérifie que vous utilisez uniquement les clés autorisées. \n
Record vs objet simple : un exemple parlant
\n\nPrenons les statuts d'une commande : pending, shipped, delivered. Sans Record, il faudrait écrire une interface avec trois champs :
interface OrderStatusMap {\n pending: string;\n shipped: string;\n delivered: string;\n}\n\nconst statusDescriptions: OrderStatusMap = {\n pending: 'En attente de traitement',\n shipped: 'Expédiée',\n delivered: 'Livrée'\n};\n\nAvec Record, c'est plus compact et plus lisible :
\n\ntype OrderStatus = 'pending' | 'shipped' | 'delivered';\n\nconst statusDescriptions: Record<OrderStatus, string> = {\n pending: 'En attente de traitement',\n shipped: 'Expédiée',\n delivered: 'Livrée'\n};\n\nAvantage : si vous essayez d'ajouter cancelled à l'objet, TypeScript signalera immédiatement une erreur — ce statut n'existe pas dans le type union.
Top 5 des exemples pratiques d'utilisation de Record
\n\nVoyons où Record simplifie vraiment la vie.
\n\n1. Configuration d'application
\nStockez des paramètres avec des clés connues mais des types de valeurs différents :
\n\ntype ConfigKeys = 'apiUrl' | 'timeout' | 'retryCount';\ntype ConfigValue = string | number | boolean;\n\nconst appConfig: Record<ConfigKeys, ConfigValue> = {\n apiUrl: 'https://api.example.com',\n timeout: 5000,\n retryCount: 3\n};\n\n2. Mapping d'enum ou de constantes
\nIl est fréquent de devoir associer un code à son libellé lisible :
\n\nenum HttpStatus {\n OK = 200,\n NotFound = 404,\n Error = 500\n}\n\nconst statusMessages: Record<HttpStatus, string> = {\n [HttpStatus.OK]: 'Tout va bien',\n [HttpStatus.NotFound]: 'Non trouvé',\n [HttpStatus.Error]: 'Erreur serveur'\n};\n\n3. Formulaires et validation
\nRecord est parfait pour stocker les erreurs de validation par champ :
\n\ntype FormFields = 'email' | 'password' | 'name';\ntype ValidationErrors = Record<FormFields, string | null>;\n\nconst errors: ValidationErrors = {\n email: 'Email invalide',\n password: null,\n name: 'Le nom est requis'\n};\n\n4. Cache de données
\nSimulation d'un cache avec des clés d'identification :
\n\ntype UserI