Introduction : pourquoi un seul type, c'est ennuyeux ?
\n\nImaginez : vous écrivez en TypeScript et vous vous retrouvez soudainement dans une situation où un tableau doit stocker des données de types différents. Par exemple, une liste où chaque élément est soit une string, soit un number. Ou un tuple composé d'un nom (chaîne) et d'un âge (nombre).
De nombreux débutants (et pas seulement) se demandent : « Comment déclarer un tableau avec plusieurs types en TypeScript ? » Cette question a recueilli des milliers de vues sur Stack Overflow – et pour cause. TypeScript est strict avec les types, mais offre des outils flexibles pour de tels cas.
\n\nDans cet article, nous allons explorer toutes les méthodes pour travailler avec des tableaux de types mixtes : des simples types unions aux tuples et aux génériques. Vous apprendrez quand utiliser chaque approche et comment éviter le piège du any.
1. Types Unions : la méthode la plus simple
\n\nL'option la plus évidente est d'utiliser un type union (union de types). Cela signifie que vous dites : « Le tableau peut contenir des éléments de type string OU number ».
// Tableau pouvant contenir des chaînes ou des nombres\nconst mixedArray: (string | number)[] = ['hello', 42, 'world', 100];\n\n// Écriture alternative (équivalente)\nconst mixedArray2: Array<string | number> = ['hello', 42, 'world', 100];\n\nIci, (string | number)[] signifie : « tableau dont chaque élément est une chaîne ou un nombre ». TypeScript vérifiera que vous n'essayez pas d'ajouter, par exemple, une valeur booléenne ou un objet.
Quand est-ce pratique ?
\n- \n
- Lorsque l'ordre des éléments n'a pas d'importance, seul l'ensemble des types autorisés compte. \n
- Lorsque vous travaillez avec une API qui renvoie un tableau de données hétérogènes. \n
- Lorsque vous stockez une liste d'ID (nombres) et de noms (chaînes) dans un même tableau. \n
Piège à éviter
\nAvec les types unions, vous ne pouvez pas garantir qu'en première position il y aura une chaîne et en deuxième un nombre. Le typage indique seulement : « le tableau contient des chaînes et des nombres, mais dans quel ordre – inconnu ».
\n\nconst arr: (string | number)[] = [1, 'hello'];\n// TypeScript ne sait pas : arr[0] est un number ou une string ?\nconst first = arr[0]; // type : string | number\n// Pour l'utiliser comme nombre, il faut réduire le type :\nif (typeof first === 'number') {\n console.log(first.toFixed(2));\n}\n\n2. Tuples : quand l'ordre est important
\n\nSi vous avez besoin que le tableau ait une structure fixe – par exemple, d'abord une chaîne, ensuite un nombre, puis un booléen – utilisez des tuples (types tuples).
\n\n// Tuple : [chaîne, nombre, booléen]\nconst person: [string, number, boolean] = ['Alice', 30, true];\n\n// Tuple avec étiquettes (labels) – plus lisible\nconst product: [name: string, price: number, inStock: boolean] = ['Laptop', 1200, true];\n\nLes tuples fixent strictement le nombre d'éléments et le type à chaque position. Si vous essayez d'assigner une valeur d'un mauvais type ou d'ajouter un élément supplémentaire, TypeScript générera une erreur.
\n\nÉléments rest dans les tuples
\nDepuis TypeScript 4.0, il est possible d'indiquer des éléments rest dans les tuples. C'est pratique lorsqu'une partie de la structure est fixe et que le reste est variable :
\n\n// Premier élément – chaîne, les autres – nombres\nconst data: [string, ...number[]] = ['scores', 95, 87, 92];\n\n// On peut combiner\nconst logEntry: [timestamp: Date, ...messages: string[]] = [new Date(), 'info', 'user logged in'];\n\n3. Alias de type pour les tableaux complexes
\n\nLorsque la structure du tableau devient complexe, il est pratique de définir le type dans un alias séparé. Cela améliore la lisibilité du code et permet de réutiliser le type.
\n\ntype UserEntry = [id: number, name: string, email: string, isActive: boolean];\n\nconst users: UserE