Un tipo array en TypeScript es el tipo de los elementos seguido de []: string[] es un array de strings, number[] un array de números. La forma genérica Array<string> es el mismo tipo. Una vez tipado el array, cada elemento que añades y cada elemento que lees tiene ese tipo.
La línea con @ts-expect-error es un error de compilación (TS2345). Aquí se marca como esperado para que el bloque se ejecute igualmente, y como los tipos se borran, el 42 sí se añade en tiempo de ejecución: la salida lo muestra.
string[] frente a Array<string>
| Se escribe | Equivale a | Notas |
|---|---|---|
string[] | Array<string> | La forma habitual. |
(string | number)[] | Array<string | number> | Los paréntesis son obligatorios: string | number[] significa «un string, o un array de números». |
readonly string[] | ReadonlyArray<string> | Sin push, pop, sort ni asignación por índice. |
User[] | Array<User> | Los arrays de objetos usan el tipo del objeto. |
string[][] | Array<Array<string>> | Un array 2D (cuadrícula). |
Elige un estilo para todo el código. La regla array-type de typescript-eslint usa T[] por defecto.
Arrays de objetos
Describe el elemento con un alias de tipo o una interfaz y luego usa Type[]. Todo lo que lees del array se comprueba contra esa forma.
Un objeto literal que añades a users debe coincidir exactamente con User: si falta admin o una propiedad está mal escrita, es un error de compilación.
map, filter, reduce y find tipados
Los métodos de array son genéricos, así que sus resultados llevan tipo. Lo que hace cada método en tiempo de ejecución está en la página de métodos de array de JavaScript; los tipos son lo que añade TypeScript:
| Método | Tipo del resultado sobre T[] |
|---|---|
map(fn) | U[], donde U es lo que devuelve fn |
filter(fn) | T[] (o un tipo más estrecho, ver abajo) |
find(fn) | T | undefined |
findIndex(fn), indexOf(x) | number (-1 si no está) |
some(fn), every(fn), includes(x) | boolean |
reduce(fn, init) | el tipo de init (o el argumento de tipo, reduce<R>(...)) |
at(i) | T | undefined |
join(sep) | string |
El último ejemplo funciona porque TypeScript (desde la 5.5) infiere que (n) => n !== undefined es un predicado de tipo, así que filter devuelve number[] en lugar de (number | undefined)[]. Para comprobaciones que no puede inferir, escribe tú el predicado: filter((x): x is User => x !== null).
Arrays con más de un tipo
Una unión como tipo de elemento permite mezclar. Una unión de tipos array no:
Cuando las posiciones tienen tipos fijos, como un par [name, age], usa una tupla: [string, number] sabe que el índice 0 es un string y el índice 1 un número, y (string | number)[] no lo sabe.
Arrays readonly
readonly T[] elimina todos los métodos que modifican el array. Úsalo para parámetros que una función no debe cambiar y para constantes.
index.ts(3,12): error TS2339: Property 'push' does not exist on type 'readonly number[]'.
Borra la línea del push y el bloque imprime 4. Un number[] mutable siempre se puede pasar donde se espera readonly number[], así que los parámetros readonly no le cuestan nada a quien llama. La comprobación es solo en tiempo de compilación: en tiempo de ejecución es un array normal. Para ordenar un array readonly, ordena una copia: [...values].sort().
La trampa de includes con arrays de literales
as const convierte un array en una tupla readonly de tipos literales. Es útil para una lista de valores permitidos, pero entonces su includes solo acepta esos literales:
Meter la comprobación en un type guard (value is Color) hace que el ensanchamiento ocurra una sola vez, y quien llama recibe un valor ya estrechado.
Indexación y arrays vacíos
Leer arr[i] da tipo T, incluso cuando i está fuera de rango y el valor en tiempo de ejecución es undefined. at(i) tiene tipo T | undefined, y la opción del compilador noUncheckedIndexedAccess hace que la indexación simple también devuelva T | undefined.
queue[0].toUpperCase() compilaría y luego lanzaría un TypeError en tiempo de ejecución. Prefiere at(), una comprobación de longitud o noUncheckedIndexedAccess cuando un índice puede faltar.
Preguntas frecuentes
¿Cómo se declara un tipo array en TypeScript?
Escribe el tipo de los elementos seguido de []: let names: string[] = ["a", "b"]. La forma genérica Array<string> significa exactamente lo mismo. Para un array de objetos, usa un tipo objeto o una interfaz como tipo de elemento: User[].
¿Qué diferencia hay entre string[] y Array<string>?
Ninguna: son dos formas de escribir el mismo tipo. string[] es más habitual. La forma genérica se lee mejor con tipos de elemento complejos, y en arrays readonly readonly string[] y ReadonlyArray<string> también son lo mismo.
¿Por qué find devuelve undefined en TypeScript?
array.find() devuelve T | undefined porque puede que nada coincida. Con strict debes manejar el caso undefined antes de usar el resultado, con un if, con encadenamiento opcional (found?.name) o con un valor por defecto (found ?? fallback).
¿Cómo tipo un array con varios tipos en TypeScript?
Usa una unión como tipo de elemento, entre paréntesis: (string | number)[] es un array en el que cada elemento es un string o un número. Es distinto de string[] | number[], que es o bien un array solo de strings o bien un array solo de números. Para un orden fijo de tipos, como [string, number], usa una tupla.
¿Por qué includes da error en un array as const?
as const?Un array readonly de literales, como ["red", "green"] as const, tiene includes(searchElement: "red" | "green"), así que pasarle un string normal es el error TS2345. Ensancha el array para la comprobación, (COLORS as readonly string[]).includes(input), idealmente dentro de un type guard que estreche input a la unión de literales.