Menu

Array em TypeScript: tipos, array de objetos, map e filter

Como tipar arrays em TypeScript: T[] vs Array<T>, arrays de objetos, arrays com vários tipos, arrays readonly e o que map, filter, reduce e find retornam. Mais a armadilha do includes com arrays de literais.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Um tipo de array em TypeScript é o tipo do elemento seguido de []: string[] é um array de strings, number[] um array de números. A grafia genérica Array<string> é o mesmo tipo. Depois que um array está tipado, todo elemento que você adiciona e todo elemento que você lê tem esse tipo.

A linha com @ts-expect-error é um erro de compilação (TS2345). Aqui ela está marcada como esperada para que o bloco ainda rode e, como os tipos são apagados, o 42 é mesmo adicionado em tempo de execução: a saída mostra isso.

string[] vs Array<string>

Escrito comoIgual aObservações
string[]Array<string>A grafia mais comum.
(string | number)[]Array<string | number>Os parênteses são obrigatórios: string | number[] significa "uma string, ou um array de números".
readonly string[]ReadonlyArray<string>Sem push, pop, sort nem atribuição por índice.
User[]Array<User>Arrays de objetos usam o tipo do objeto.
string[][]Array<Array<string>>Um array 2D (grade).

Escolha um estilo para o projeto. A regra array-type do typescript-eslint usa T[] por padrão.

Arrays de objetos

Descreva o elemento com um type alias ou uma interface e depois use Type[]. Tudo o que sai do array é verificado contra esse formato.

Um objeto literal adicionado a users precisa corresponder exatamente a User: um admin ausente ou uma propriedade com nome errado é erro de compilação.

map, filter, reduce e find tipados

Os métodos de array são genéricos, então seus resultados carregam tipos. O que cada método faz em tempo de execução está na página de métodos de array do JavaScript; os tipos são o que o TypeScript acrescenta:

MétodoTipo do resultado em T[]
map(fn)U[], em que U é o que fn retorna
filter(fn)T[] (ou um tipo mais estreito, veja abaixo)
find(fn)T | undefined
findIndex(fn), indexOf(x)number (-1 se não houver)
some(fn), every(fn), includes(x)boolean
reduce(fn, init)o tipo de init (ou o argumento de tipo, reduce<R>(...))
at(i)T | undefined
join(sep)string

O último exemplo funciona porque o TypeScript (desde a versão 5.5) infere que (n) => n !== undefined é um type predicate, então filter retorna number[] em vez de (number | undefined)[]. Para verificações que ele não consegue inferir, escreva o predicate você mesmo: filter((x): x is User => x !== null).

Arrays com mais de um tipo

Um tipo de elemento union permite misturar. Uma union de tipos de array não permite:

Quando as posições têm tipos fixos, como um par [name, age], use uma tupla: [string, number] sabe que o índice 0 é uma string e o índice 1 é um número, o que (string | number)[] não sabe.

Arrays readonly

readonly T[] remove todo método que modifica o array. Use em parâmetros que a função não deve alterar e em constantes.

index.ts(3,12): error TS2339: Property 'push' does not exist on type 'readonly number[]'.

Apague a linha do push e o bloco imprime 4. Um number[] mutável sempre pode ser passado onde se espera readonly number[], então parâmetros readonly não custam nada para quem chama. A verificação só existe em tempo de compilação: em tempo de execução é um array comum. Para ordenar um array readonly, ordene uma cópia: [...values].sort().

A armadilha do includes com arrays de literais

as const transforma um array em uma tupla readonly de tipos literais. Isso é útil para uma lista de valores permitidos, mas aí o includes dela só aceita esses literais:

Colocar a verificação dentro de um type guard (value is Color) faz o alargamento acontecer uma vez só, e quem chama recebe de volta um valor estreitado.

Índices e arrays vazios

Ler arr[i] dá o tipo T, mesmo quando i está fora do intervalo e o valor em tempo de execução é undefined. at(i) tem o tipo T | undefined, e a opção de compilador noUncheckedIndexedAccess faz o acesso por índice simples retornar T | undefined também.

queue[0].toUpperCase() compilaria e depois lançaria um TypeError em tempo de execução. Prefira at(), uma verificação de tamanho ou noUncheckedIndexedAccess quando um índice pode não existir.

Perguntas frequentes

Como declarar um tipo de array no TypeScript?

Escreva o tipo do elemento seguido de []: let names: string[] = ["a", "b"]. A forma genérica Array<string> significa exatamente a mesma coisa. Para um array de objetos, use um tipo de objeto ou uma interface como tipo do elemento: User[].

Qual é a diferença entre string[] e Array<string>?

Nenhuma: são duas grafias do mesmo tipo. string[] é a mais comum. A forma genérica fica mais legível com tipos de elemento complexos, e para arrays readonly readonly string[] e ReadonlyArray<string> também são iguais.

Por que find retorna undefined no TypeScript?

array.find() retorna T | undefined porque pode ser que nada corresponda. Com strict você precisa tratar o caso undefined, com uma verificação if, optional chaining (found?.name) ou um valor padrão (found ?? fallback), antes de usar o resultado.

Como tipar um array com vários tipos no TypeScript?

Use um tipo de elemento union entre parênteses: (string | number)[] é um array em que cada elemento é string ou number. Isso é diferente de string[] | number[], que é um array só de strings ou um array só de números. Para uma ordem fixa de tipos, como [string, number], use uma tupla.

Por que includes dá erro em um array as const?

Um array readonly de literais, como ["red", "green"] as const, tem includes(searchElement: "red" | "green"), então passar uma string comum é o erro TS2345. Alargue o array para a verificação, (COLORS as readonly string[]).includes(input), de preferência dentro de um type guard que estreite input para a union de literais.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR