Introducción: ¿por qué un solo tipo es aburrido?
\n\nImagine: está escribiendo en TypeScript y de repente se encuentra con una situación en la que un arreglo debe almacenar datos de diferentes tipos. Por ejemplo, una lista donde cada elemento es un string o un number. O una tupla de un nombre (string) y una edad (número).
Muchos principiantes (y no solo) se preguntan: «¿Cómo declaro un arreglo con varios tipos en TypeScript?» Esta pregunta ha obtenido miles de visitas en Stack Overflow, y con razón. TypeScript es estricto con los tipos, pero ofrece herramientas flexibles para estos casos.
\n\nEn este artículo, analizaremos todas las formas de trabajar con arreglos de tipos mixtos: desde simples union types hasta tuplas y genéricos. Aprenderá cuándo usar cada enfoque y cómo no caer en la trampa de any.
1. Union Types: la forma más sencilla
\n\nLa opción más obvia es usar un union type (unión de tipos). Esto es cuando usted dice: «El arreglo puede contener elementos de tipo string O number».
// Arreglo que puede contener strings o números\nconst mixedArray: (string | number)[] = ['hola', 42, 'mundo', 100];\n\n// Notación alternativa (equivalente)\nconst mixedArray2: Array<string | number> = ['hola', 42, 'mundo', 100];\n\nAquí (string | number)[] significa: «arreglo, donde cada elemento es un string o un número». TypeScript verificará que no intente agregar, por ejemplo, un valor booleano o un objeto.
¿Cuándo es útil?
\n- \n
- Cuando el orden de los elementos no importa, solo importa el conjunto de tipos permitidos. \n
- Cuando trabaja con una API que devuelve un arreglo de datos heterogéneos. \n
- Cuando almacena una lista de IDs (números) y nombres (strings) en un mismo arreglo. \n
La trampa oculta
\nAl usar union types, no puede garantizar que en la primera posición haya un string y en la segunda un número. La tipificación solo dice: «en el arreglo hay strings y números, pero en qué orden se desconoce».
\n\nconst arr: (string | number)[] = [1, 'hola'];\n// TypeScript no sabe: ¿arr[0] es number o string?\nconst first = arr[0]; // tipo: string | number\n// Para usarlo como número, necesita reducir el tipo:\nif (typeof first === 'number') {\n console.log(first.toFixed(2));\n}\n\n2. Tuplas: cuando el orden importa
\n\nSi necesita que el arreglo tenga una estructura fija — por ejemplo, primero un string, segundo un número, tercero un valor booleano — use tuplas (tuple types).
\n\n// Tupla: [string, número, booleano]\nconst person: [string, number, boolean] = ['Alicia', 30, true];\n\n// Tupla con etiquetas (labels) — más legible\nconst product: [name: string, price: number, inStock: boolean] = ['Laptop', 1200, true];\n\nLas tuplas fijan estrictamente la cantidad de elementos y el tipo en cada posición. Si intenta asignar un valor de un tipo incorrecto o agregar un elemento extra, TypeScript mostrará un error.
\n\nElementos Rest en tuplas
\nCon TypeScript 4.0, es posible indicar elementos rest en las tuplas. Esto es útil cuando parte de la estructura es fija y el resto es variable:
\n\n// Primer elemento es un string, el resto son números\nconst data: [string, ...number[]] = ['puntajes', 95, 87, 92];\n\n// Se puede combinar\nconst logEntry: [timestamp: Date, ...messages: string[]] = [new Date(), 'info', 'usuario inició sesión'];\n\n3. Type Alias para arreglos complejos
\n\nCuando la estructura del arreglo se vuelve compleja, es conveniente extraer el tipo en un alias (seudónimo) separado. Esto mejora la legibilidad del código y permite reutilizar el tipo.
\n\ntype UserEntry = [id: number, name: string, email: string, isActive: boolean];\n\nconst users: UserE