Introdução: por que um único tipo é chato?
\n\nImagine: você está programando em TypeScript e de repente se depara com uma situação em que o array precisa armazenar dados de tipos diferentes. Por exemplo, uma lista onde cada elemento é ou string ou number. Ou uma tupla com um nome (string) e uma idade (número).
Muitos iniciantes (e não só) se perguntam: "Como declarar um array com vários tipos em TypeScript?" Essa pergunta tem milhares de visualizações no Stack Overflow — e não é à toa. TypeScript é rigoroso com tipos, mas oferece ferramentas flexíveis para esses casos.
\n\nNeste artigo, vamos abordar todas as formas de trabalhar com arrays de tipos mistos: desde union types simples até tuplas e genéricos. Você aprenderá quando usar cada abordagem e como não cair na armadilha do any.
1. Union Types: a maneira mais simples
\n\nA opção mais óbvia é usar union type (união de tipos). É quando você diz: "O array pode conter elementos do tipo string OU number".
// Array que pode conter strings ou números\nconst mixedArray: (string | number)[] = ['hello', 42, 'world', 100];\n\n// Notação alternativa (equivalente)\nconst mixedArray2: Array<string | number> = ['hello', 42, 'world', 100];\n\nAqui, (string | number)[] significa: "array onde cada elemento é uma string ou um número". O TypeScript verificará se você não tenta adicionar, por exemplo, um valor booleano ou um objeto.
Quando é útil?
\n- \n
- Quando a ordem dos elementos não importa, apenas o conjunto de tipos permitidos. \n
- Quando você trabalha com uma API que retorna um array de dados heterogêneos. \n
- Quando você armazena uma lista de IDs (números) e nomes (strings) em um único array. \n
Armadilha
\nAo usar union types, você não pode garantir que na primeira posição haverá uma string e na segunda, um número. A tipagem apenas diz: "no array há strings e números, mas em qual ordem — é desconhecido".
\n\nconst arr: (string | number)[] = [1, 'hello'];\n// TypeScript não sabe: arr[0] é number ou string?\nconst first = arr[0]; // tipo: string | number\n// Para usar como número, é necessário restringir o tipo:\nif (typeof first === 'number') {\n console.log(first.toFixed(2));\n}\n\n2. Tuplas: quando a ordem importa
\n\nSe você precisa que o array tenha uma estrutura fixa — por exemplo, primeiro uma string, segundo um número, terceiro um valor booleano — use tuplas (tuple types).
\n\n// Tupla: [string, número, booleano]\nconst person: [string, number, boolean] = ['Alice', 30, true];\n\n// Tupla com rótulos (labels) — mais legível\nconst product: [name: string, price: number, inStock: boolean] = ['Laptop', 1200, true];\n\nAs tuplas fixam rigorosamente a quantidade de elementos e o tipo em cada posição. Se você tentar atribuir um valor de tipo incorreto ou adicionar um elemento extra, o TypeScript emitirá um erro.
\n\nElementos Rest em tuplas
\nCom o TypeScript 4.0, tornou-se possível especificar elementos rest em tuplas. Isso é útil quando parte da estrutura é fixa e o restante é variável:
\n\n// Primeiro elemento é string, os demais são números\nconst data: [string, ...number[]] = ['scores', 95, 87, 92];\n\n// Pode-se combinar\nconst logEntry: [timestamp: Date, ...messages: string[]] = [new Date(), 'info', 'user logged in'];\n\n3. Type Alias para arrays complexos
\n\nQuando a estrutura do array se torna complexa, é conveniente extrair o tipo para um alias (apelido) separado. Isso melhora a legibilidade do código e permite reutilizar o tipo.
\n\ntype UserEntry = [id: number, name: string, email: string, isActive: boolean];\n\nconst users: UserE