Definire e gestire gli array in TypeScript

Gli array permettono di memorizzare più valori all'interno di un'unica struttura. In TypeScript possiamo specificare il tipo degli elementi che un array può contenere, ottenendo così controlli più precisi durante lo sviluppo.

Per esempio, possiamo dichiarare un array che contiene esclusivamente stringhe:

const nomi: string[] = ["Andrea", "Luca", "Anna"];

TypeScript controllerà quindi che tutti gli elementi siano compatibili con il tipo string.

In questa lezione vedremo come definire gli array, come gestire più tipi all'interno dello stesso array e come impedire che un array venga modificato.

Definire un array

Il modo più comune per specificare il tipo di un array consiste nell'utilizzare la sintassi tipo[].

Ad esempio:

const nomi: string[] = ["Andrea", "Luca", "Anna"];
const eta: number[] = [20, 25, 30];
const attivi: boolean[] = [true, false, true];

Nell'esempio, la sintassi string[] significa un array di stringhe. Analogamente, number[] indica un array i cui elementi sono numeri.

Anche per gli array TypeScript può utilizzare la Type Inference, che abbiamo visto nella lezione su come definire i tipi di valori in TypeScript. Ad esempio, possiamo scrivere:

const nomi = ["Andrea", "Luca", "Anna"];

TypeScript deduce automaticamente il tipo string in base al contenuto dell'array.

La sintassi Array<tipo>

Esiste anche una seconda sintassi equivalente: Array<tipo>. Ad esempio:

const nomi: Array<string> = ["Andrea", "Luca", "Anna"];

L'esempio è equivalente a utilizzare la sintassi string[].

Allo stesso modo, possiamo utilizzare anche altri tipi di valore:

const eta: Array<number> = [20, 25, 30];
const attivi: Array<boolean> = [true, false, true];

Array di più tipi

Possiamo avere la necessità di creare un array che possa contenere valori di tipi differenti. Per farlo possiamo utilizzare un'unione di tipi.

Per dichiarare più tipi, possiamo racchiuderli all'interno delle parentesi tonde e divisi da |:

const dati: (string | number)[] = ["Andrea", 30, "Anna", 25];

La parte string | number significa che ogni elemento dell'array può essere una string oppure un number.

Array di oggetti

Gli array possono contenere anche valori più complessi, come gli oggetti. Ad esempio, possiamo scrivere un oggetto formato dalle proprietà nome e eta:

const utenti: { nome: string; eta: number }[] = [
    { nome: "Andrea", eta: 30 },
    { nome: "Marco", eta: 25 }
];

Aggiungere elementi all'array

Possiamo aggiungere elementi all'interno di un array in TypeScript utilizzando il metodo push(), come viene fatto anche in JavaScript.

Ad esempio, consideriamo:

const nomi: string[] = ["Andrea", "Luca"];

Possiamo utilizzare push() per aggiungere una stringa:

nomi.push("Anna");

Visto che abbiamo dichiarato string[], non possiamo aggiungere un numero:

nomi.push(30);

Con un array definito con tipi string e number, possiamo aggiungere entrambi i tipi:

const dati: (string | number)[] = ["Andrea", 30];
dati.push("Anna");
dati.push(40);

Rimuovere l'ultimo elemento dall'array

Possiamo rimuovere l'ultimo elemento dell'array con il metodo pop() in TypeScript.

Per esempio, per rimuovere Luca:

const nomi: string[] = ["Andrea", "Luca"];

const nome = nomi.pop();

TypeScript sa che il valore restituito può essere una stringa, ma anche non definito (undefined), nel caso in cui l'array sia vuoto. Il tipo di nome sarà quindi string | undefined.

Gestire gli elementi di un array

Esistono alcuni metodi per gestire gli elementi degli array in TypeScript: map() e filter().

Il metodo map()

Il metodo map() permette di creare un nuovo array trasformando ogni elemento di quello originale.

Per esempio:

const numeri: number[] = [1, 2, 3];

const doppi = numeri.map(numero => numero * 2);

TypeScript sa che numero è un number perché l'array di partenza è un number[]. Di conseguenza, sa anche che il nuovo array contiene numeri.

Possiamo anche trasformare i numeri in stringhe:

const numeri: number[] = [1, 2, 3];

const testi = numeri.map(numero => `Numero: ${numero}`);

Con map(), possiamo estrarre singole proprietà dagli oggetti per creare un nuovo array:

const utenti: { nome: string; eta: number }[] = [
    { nome: "Andrea", eta: 30 },
    { nome: "Marco", eta: 25 }
];

const nomi = utenti.map(utente => utente.nome);

Il metodo filter()

Il metodo filter() permette di creare un nuovo array contenente soltanto gli elementi che rispettano una determinata condizione.

Ad esempio:

const numeri: number[] = [10, 15, 20, 25];

const maggiori = numeri.filter(numero => numero > 15);

Anche in questo caso, TypeScript conosce il tipo degli elementi: il nuovo array maggiori sarà anch'esso di tipo number[].

Array non modificabili

Normalmente possiamo modificare un array dopo averlo creato, ad esempio con i metodi push() e pop(). Se invece vogliamo impedire che gli elementi vengano modificati, possiamo utilizzare readonly.

Ad esempio, per rendere immutabile nomi:

const nomi: readonly string[] = ["Andrea", "Luca"];

Possiamo anche utilizzare la sintassi ReadonlyArray<tipo>:

const nomi: ReadonlyArray<string> = ["Andrea", "Luca"];

A questo punto non possiamo utilizzare operazioni che modificano direttamente l'array, ad esempio push():

nomi.push("Anna"); // Errore

Prova!Completa gli spazi vuoti con il testo appropriato.
// Rendi l'array non modificabile
const codici: number[] = [22, 33, 44];

codici.pop(); // Errore

Prova! Scegli l'opzione corretta tra quelle elencate.
// Crea un array con soli elementi voto < 6
const voti: number[] = [6, 7, 8, 9];

const insufficienti = voti._____(voto => voto < 6);