Comment assigner dynamiquement des propriétés à un objet en TypeScript ? Explication claire pour débutants
\n\nSalut, l'ami ! Si tu as déjà écrit en JavaScript, puis migré vers TypeScript, tu as sûrement rencontré une situation où tu dois ajouter une nouvelle propriété à un objet à la volée. En JS, cela se fait en deux temps : obj.newProp = 'value'. Mais dès que tu essaies la même chose en TypeScript, le compilateur se met à râler : "Property 'newProp' does not exist on type ...". Ça te dit quelque chose ?
Ne t'inquiète pas, c'est normal. TypeScript nous protège des erreurs accidentelles, mais parfois sa rigueur semble excessive. Dans cet article, nous allons voir comment assigner dynamiquement des propriétés aux objets de manière correcte et sécurisée. Tu découvriras plusieurs méthodes éprouvées – des plus simples aux plus élégantes. C'est parti !
\n\nPourquoi TypeScript râle-t-il ?
\n\nAvant de résoudre le problème, comprenons sa racine. TypeScript est une surcouche de JavaScript qui ajoute le typage statique. Lorsque tu déclares un objet :
\n\nconst user = { name: 'Анна', age: 25 };\n\n\nTypeScript déduit automatiquement son type : { name: string; age: number }. Cela signifie que l'objet user ne peut contenir que ces deux propriétés. Essayer d'ajouter email provoquera une erreur de compilation :
user.email = 'anna@example.com'; // ❌ Erreur !\n\n\nTypeScript ne sait pas qu'une telle propriété peut apparaître et bloque le code. Mais dans la vraie vie, on a souvent besoin d'ajouter des propriétés dynamiquement – par exemple, lorsqu'on travaille avec des données provenant d'une API ou de formulaires. Voyons comment faire cela correctement.
\n\nMéthode 1 : La plus simple — as any
\n\nUne méthode rapide mais sale consiste à utiliser as any. Elle dit littéralement à TypeScript : « Désactive la vérification de type pour cet objet ».
const user: any = { name: 'Анна', age: 25 };\nuser.email = 'anna@example.com'; // ✅ Fonctionne\nuser.isAdmin = true; // ✅ Fonctionne\n\n\nPourquoi est-ce mauvais ? Parce que tu perds tous les avantages de TypeScript : l'autocomplétion, la vérification des types, la protection contre les fautes de frappe. Si tu écris accidentellement user.emial, il n'y aura pas d'erreur – tu ne le sauras qu'à l'exécution. Utilise cette méthode uniquement pour un prototypage rapide ou lorsque tu sais exactement ce que tu fais.
Méthode 2 : La signature d'index (Index Signature)
\n\nUne approche plus correcte consiste à déclarer à l'avance que l'objet peut contenir des propriétés dynamiques. Pour cela, on utilise une signature d'index.
\n\ninterface User {\n name: string;\n age: number;\n [key: string]: any; // 👈 Permet toutes les propriétés supplémentaires\n}\n\nconst user: User = { name: 'Анна', age: 25 };\nuser.email = 'anna@example.com'; // ✅ Fonctionne\nuser.phone = '+7-999-123-45-67'; // ✅ Fonctionne\n\n\nQue se passe-t-il ici ? L'écriture [key: string]: any signifie : « l'objet peut avoir n'importe quelle clé de type chaîne, et ses valeurs peuvent être de n'importe quel type ». Maintenant, tu peux ajouter des propriétés dynamiquement, et TypeScript ne râlera pas.
Nuance importante : si tu veux limiter les types de valeurs, remplace any par un type spécifique :
interface User {\n name: string;\n age: number;\n [key: string]: string | number; // Uniquement des chaînes et des nombres\n}\n\n\nLa signature d'index est un excellent choix lorsque tu sais à l'avance que l'objet va s'étendre. Mais attention : si l'interface contient d'autres propriétés avec d'autres types, elles doivent aussi correspondre à la signature.
\n\nMéthode 3 : Le type utilitaire Record
\n\nSi tu as besoin de créer un objet où toutes les clés et toutes les valeurs sont du même type, utilise le type intégré Record<Keys, Type>. Il est parfait pour les dictionnaires ou les mappings.
type UserRoles = Record<string, 'admin' | 'user' | 'guest'>;\n\nconst roles: UserRoles = {\n anna: 'admin',\n ivan: 'user',\n};\