Menu

Array in TypeScript: tipi, array di oggetti, map e filter

Come tipizzare gli array in TypeScript: T[] vs Array<T>, array di oggetti, array con più tipi, array readonly e cosa restituiscono map, filter, reduce e find. In più la trappola di includes con gli array di letterali.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Un tipo array in TypeScript è il tipo dell'elemento seguito da []: string[] è un array di stringhe, number[] un array di numeri. La forma generica Array<string> è lo stesso tipo. Una volta tipizzato un array, ogni elemento che aggiungi e ogni elemento che leggi ha quel tipo.

La riga @ts-expect-error è un errore di compilazione (TS2345). Qui è marcata come attesa così il blocco viene eseguito lo stesso, e dato che i tipi vengono cancellati, il 42 viene davvero aggiunto a runtime: l'output lo mostra.

string[] vs Array<string>

Scritto comeUguale aNote
string[]Array<string>La forma comune.
(string | number)[]Array<string | number>Le parentesi sono obbligatorie: string | number[] significa "una stringa, o un array di numeri".
readonly string[]ReadonlyArray<string>Niente push, pop, sort né assegnazione per indice.
User[]Array<User>Gli array di oggetti usano il tipo dell'oggetto.
string[][]Array<Array<string>>Un array 2D (griglia).

Scegli uno stile per tutto il codebase. La regola array-type di typescript-eslint usa T[] come predefinito.

Array di oggetti

Descrivi l'elemento con un type alias o un'interfaccia, poi usa Type[]. Tutto ciò che leggi dall'array viene controllato rispetto a quella forma.

Un oggetto letterale aggiunto a users deve corrispondere esattamente a User: un admin mancante o una proprietà scritta male è un errore di compilazione.

map, filter, reduce e find tipizzati

I metodi degli array sono generici, quindi i loro risultati portano con sé i tipi. Cosa fa ogni metodo a runtime è spiegato nella pagina JavaScript sui metodi degli array; i tipi sono ciò che aggiunge TypeScript:

MetodoTipo del risultato su T[]
map(fn)U[], dove U è ciò che restituisce fn
filter(fn)T[] (o un tipo più stretto, vedi sotto)
find(fn)T | undefined
findIndex(fn), indexOf(x)number (-1 se assente)
some(fn), every(fn), includes(x)boolean
reduce(fn, init)il tipo di init (o l'argomento di tipo, reduce<R>(...))
at(i)T | undefined
join(sep)string

L'ultimo esempio funziona perché TypeScript (dalla 5.5) deduce che (n) => n !== undefined è un type predicate, quindi filter restituisce number[] invece di (number | undefined)[]. Per i controlli che non riesce a dedurre, scrivi tu il predicato: filter((x): x is User => x !== null).

Array che contengono più di un tipo

Un tipo elemento union permette di mescolare. Una union di tipi array no:

Quando le posizioni hanno tipi fissi, come una coppia [name, age], usa invece una tupla: [string, number] sa che l'indice 0 è una stringa e l'indice 1 è un numero, mentre (string | number)[] no.

Array readonly

readonly T[] elimina ogni metodo che modifica l'array. Usalo per i parametri che una funzione non deve cambiare e per le costanti.

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

Elimina la riga con push e il blocco stampa 4. Un number[] modificabile si può sempre passare dove è atteso readonly number[], quindi i parametri readonly non costano nulla a chi chiama. Il controllo avviene solo in compilazione: a runtime è un array normale. Per ordinare un array readonly, ordina una copia: [...values].sort().

La trappola di includes con gli array di letterali

as const trasforma un array in una tupla readonly di tipi letterali. È utile per un elenco di valori ammessi, ma a quel punto il suo includes accetta solo quei letterali:

Avvolgere il controllo in una type guard (value is Color) fa sì che l'allargamento avvenga una sola volta, e chi chiama riceve indietro un valore ristretto.

Indici e array vuoti

Leggere arr[i] dà il tipo T, anche quando i è fuori intervallo e il valore a runtime è undefined. at(i) è tipizzato T | undefined, e l'opzione del compilatore noUncheckedIndexedAccess fa restituire T | undefined anche all'indicizzazione normale.

queue[0].toUpperCase() compilerebbe e poi lancerebbe un TypeError a runtime. Preferisci at(), un controllo sulla lunghezza o noUncheckedIndexedAccess quando un indice potrebbe mancare.

Domande frequenti

Come si dichiara un tipo array in TypeScript?

Scrivi il tipo dell'elemento seguito da []: let names: string[] = ["a", "b"]. La forma generica Array<string> significa esattamente la stessa cosa. Per un array di oggetti, usa come tipo dell'elemento un tipo oggetto o un'interfaccia: User[].

Che differenza c'è tra string[] e Array<string>?

Nessuna: sono due modi di scrivere lo stesso tipo. string[] è più diffuso. La forma generica si legge meglio con tipi di elemento complessi, e per gli array readonly anche readonly string[] e ReadonlyArray<string> sono la stessa cosa.

Perché find restituisce undefined in TypeScript?

array.find() restituisce T | undefined perché potrebbe non esserci nessuna corrispondenza. Con strict devi gestire il caso undefined, con un controllo if, con l'optional chaining (found?.name) o con un valore predefinito (found ?? fallback), prima di usare il risultato.

Come si tipizza un array con più tipi in TypeScript?

Usa come tipo dell'elemento una union tra parentesi: (string | number)[] è un array in cui ogni elemento è una stringa o un numero. È diverso da string[] | number[], che è o un array di sole stringhe o un array di soli numeri. Per un ordine fisso di tipi, come [string, number], usa una tupla.

Perché includes dà errore su un array as const?

Un array readonly di letterali, come ["red", "green"] as const, ha includes(searchElement: "red" | "green"), quindi passare una semplice string è l'errore TS2345. Allarga l'array per il controllo, (COLORS as readonly string[]).includes(input), meglio se dentro una type guard che restringe input alla union di letterali.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA