Erreur TypeScript : index de type union — solution pour débutants

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi TypeScript râle-t-il sur votre code ?

\n\n

Avez-vous déjà écrit du code TypeScript qui semble parfaitement logique, mais le compilateur affiche soudainement une erreur effrayante ? Si vous avez déjà rencontré le message « An index signature parameter type cannot be a union type. Consider using a mapped object type instead » — vous n'êtes pas seul. Cette erreur est l'une des questions les plus populaires sur Stack Overflow (des milliers de vues !), et elle laisse souvent perplexes même les développeurs expérimentés.

\n\n

Dans cet article, nous ne montrerons pas seulement comment corriger l'erreur. Nous expliquerons pourquoi TypeScript est si strict, et comment utiliser les mapped object types pour rendre votre code non seulement fonctionnel, mais aussi plus sûr. C'est parti !

\n\n

Qu'est-ce qu'une index signature et à quoi sert-elle ?

\n\n

Imaginez que vous créez un objet dont les clés sont des chaînes de caractères et les valeurs des nombres. Par exemple, un dictionnaire des prix des produits :

\n\n
// Objet normal\nconst prices = {\n  apple: 100,\n  banana: 50,\n  cherry: 200\n};
\n\n

Mais que faire si vous voulez dire à TypeScript : « Écoute, cet objet peut avoir n'importe quelles clés de type chaîne, et toutes les valeurs seront des nombres » ? C'est là qu'intervient l'index signature — une syntaxe spéciale qui décrit un modèle pour toutes les propriétés d'un objet :

\n\n
// Index signature : [key: string]: number\ninterface PriceMap {\n  [key: string]: number;\n}\n\nconst prices: PriceMap = {\n  apple: 100,\n  banana: 50\n};
\n\n

Ici, [key: string]: number est l'index signature. Elle dit : « Les clés sont des chaînes, les valeurs sont des nombres ». Simple, non ?

\n\n

Quel est le problème avec les types union ?

\n\n

Imaginez maintenant que vous voulez limiter les clés possibles à seulement deux options : 'name' ou 'age'. Il semble logique d'écrire ceci :

\n\n
// ❌ ERREUR ! Pas possible\ninterface Person {\n  [key: 'name' | 'age']: string | number;\n}
\n\n

Et là, TypeScript affiche cette fameuse erreur : « An index signature parameter type cannot be a union type. Consider using a mapped object type instead ».

\n\n

Pourquoi ? Parce que l'index signature est conçue pour décrire un ensemble illimité de clés. Si vous voulez définir une liste spécifique de clés, ce n'est plus un modèle, mais une description précise de la structure. TypeScript ne permet pas de mélanger ces concepts.

\n\n

Comment corriger l'erreur ? Utiliser le Mapped Object Type

\n\n

La solution proposée par le compilateur lui-même est d'utiliser un mapped object type (type d'objet mappé). Cela semble compliqué, mais en réalité c'est simplement une façon de « parcourir » toutes les clés d'un type union et de créer une propriété pour chacune.

\n\n

Voici à quoi cela ressemble :

\n\n
// ✅ CORRECT : utilisation d'un mapped type\ntype Person = {\n  [K in 'name' | 'age']: K extends 'name' ? string : number;\n};\n\n// Ou une version plus simple, si les types de valeurs sont identiques :\ntype PersonSimple = {\n  [K in 'name' | 'age']: string | number;\n};
\n\n

Décortiquons la syntaxe [K in 'name' | 'age'] :

\n
    \n
  • K — est une variable qui prend successivement chaque valeur du type union ('name', puis 'age').
  • \n
  • in — est un mot-clé qui lance une « boucle » sur les types.
  • \n
  • 'name' | 'age' — est notre ensemble de clés.
  • \n
\n\n

En conséquence, TypeScript créera un objet avec deux propriétés spécifiques : name et age. L'erreur a disparu !

\n\n

Exemple avec différents types de valeurs

\n\n

Il arrive souvent que différentes clés doivent avoir différents types de valeurs. Avec les types conditionnels (conditional types), cela se résout élégamment :

\n\n
type Config = {\n  [K in 'host' | 'port' | 'debug']: \n    K extends 'host' ? string :\n    K extends 'port' ? number :\n    boolean;\n};\n\n// Maintenant :                

Blogs

Book Recommendations