Gli alias di tipo in TypeScript

Quando un tipo viene utilizzato in più punti del programma, ripeterne ogni volta la struttura rende il codice ridondante e difficile da aggiornare in futuro.

TypeScript permette di assegnare un nome a un tipo tramite la parola chiave type. Questo identificatore è detto alias di tipo e può essere riutilizzato nell'intero codebase.

Un alias di tipo non crea un nuovo tipo a runtime: definisce semplicemente un nome per una struttura di tipo esistente.

Creare un alias di tipo

Per creare un alias di tipo in TypeScript, si usa la sintassi type nomeTipo = tipo;.

Ad esempio, possiamo creare un alias per string:

type Nome = string;

A questo punto possiamo utilizzare Nome come se fosse string:

let nome: Nome = "Andrea";

Il valore deve comunque rispettare il tipo originale. Questo esempio genera un errore perché Nome corrisponde a string:

let nome: Nome = 30; // Errore

Alias per i tipi primitivi

Possiamo creare alias di tipo per qualsiasi tipologia di valore, compresi i tipi primitivi. Ad esempio:

type Eta = number;
type Attivo = boolean;
type Email = string;

Possiamo quindi utilizzarli nelle dichiarazioni:

const eta: Eta = 30;
const attivo: Attivo = true;
const email: Email = "[email protected]";

Questo può essere utile quando un determinato tipo ha un significato specifico all'interno della nostra applicazione.

Per esempio, Email è tecnicamente una string, ma il nome dell'alias rende più evidente cosa rappresenta quel valore.

Alias per gli oggetti

Gli alias di tipi diventano particolarmente utili quando vogliamo definire la struttura di un oggetto. Ad esempio, possiamo scrivere:

type Persona = {
    nome: string;
    eta: number;
};

A questo punto possiamo utilizzare Persona in più punti:

const persona1: Persona = {
    nome: "Andrea",
    eta: 30
};

const persona2: Persona = {
    nome: "Marco",
    eta: 25
};

Senza un alias, dovremmo ripetere ogni volta l'intera struttura dell'oggetto. L'alias di tipo rende quindi il codice più compatto e soprattutto evita di duplicare la definizione dello stesso tipo.

Modificare la struttura di un tipo

Uno dei vantaggi principali degli alias di tipo è la possibilità di avere un'unica definizione da mantenere aggiornata.

Riprendiamo l'esempio Persona fatto precedentemente:

type Persona = {
    nome: string;
    eta: number;
};

Se in seguito vogliamo aggiungere una proprietà, tutti i punti del programma che utilizzano Persona faranno riferimento alla nuova struttura:

type Persona = {
    nome: string;
    eta: number;
    email: string;
};

Questo è particolarmente utile nei programmi di grandi dimensioni, dove lo stesso tipo può essere utilizzato in molte funzioni e variabili.

Proprietà opzionali e readonly

All'interno di un alias possiamo utilizzare le stesse funzionalità viste per la tipizzazione degli oggetti e tuple. Per esempio, possiamo rendere facoltativo un parametro:

type Persona = {
    readonly id: number;
    nome: string;
    email?: string;
};

In questo esempio:

  • id è obbligatoria e non può essere modificata.
  • nome è obbligatoria.
  • email è opzionale.

Alias per le unioni di tipi

Un alias può rappresentare anche un'unione di tipi, che abbiamo visto nella lezione sugli array e che approfondiremo nella lezione dedicata agli operatori di unione.

Per esempio:

type ID = string | number;

Ora ID può essere utilizzato per indicare un valore che può essere una stringa oppure un numero:

let id: ID;

id = 10;
id = "abc123";

Entrambi i valori sono validi.

Questo permette di dare un nome a un'unione di tipi che potrebbe essere utilizzata in diversi punti del programma. Ad esempio:

type Stato = "attivo" | "inattivo" | "sospeso";

function cambiaStato(stato: Stato) {
    console.log(stato);
}

La funzione accetterà soltanto uno dei tre valori definiti.

Alias per le funzioni

Un alias di tipi può descrivere anche il tipo di una funzione. Per esempio:

type Operazione = (a: number, b: number) => number;

Ora possiamo utilizzare Operazione per dichiarare variabili che devono contenere funzioni compatibili:

const somma: Operazione = (a, b) => a + b;
const moltiplica: Operazione = (a, b) => a * b;

Utilizzare alias dentro alias

Gli alias di tipo possono essere utilizzati per costruire tipi più complessi partendo da altri tipi.

Per esempio, possiamo definire separatamente un indirizzo:

type Indirizzo = {
    via: string;
    citta: string;
    cap: string;
};

Poi, possiamo usare l'alias Indirizzo all'interno di un altro alias:

type Persona = {
    nome: string;
    eta: number;
    indirizzo: Indirizzo;
};

Ora un oggetto Persona dovrà contenere un oggetto Indirizzo:

const persona: Persona = {
    nome: "Andrea",
    eta: 30,
    indirizzo: {
        via: "Via Roma 10",
        citta: "Milano",
        cap: "20100"
    }
};

In questo modo possiamo suddividere strutture complesse in tipi più piccoli e facilmente riutilizzabili.

Prova!Completa gli spazi vuoti con il testo appropriato.
// Crea un alias di tipo chiamato "Colore"

Colore = "rosso" | "verde" | "blu";

let sfondo: Colore = "rosso";

Prova! Scegli l'opzione corretta tra quelle elencate.
// Indica il tipo corretto
type Veicolo = (velocita: number) => ______;
const accelera: Veicolo = (velocita) => velocita + 10;