Operatori di unione in TypeScript

In TypeScript non sempre una variabile deve accettare un solo tipo di valore. In alcuni casi può essere necessario permettere diverse alternative, limitando però con precisione i valori che possono essere utilizzati.

A questo scopo TypeScript mette a disposizione gli operatori di unione e i tipi letterali.

Gli operatori di unione

Gli operatori di unione permettono di combinare più tipi attraverso l'operatore |. In questo modo, viene specificato che un valore può appartenere a uno tra più tipi.

Ad esempio:

let id: string | number;

La variabile id può quindi contenere una stringa oppure un numero:

id = 10;
id = "ABC123";

Entrambi i valori sono validi. Questo invece genera un errore, perché boolean non fa parte dei tipi specificati:

id = true; // Errore

Unione senza alias

Non è necessario creare un alias per utilizzare un'unione di tipi. Possiamo scriverla direttamente quando dichiariamo la variabile:

let valore: string | number;

Oppure possiamo utilizzare l'unione di tipi nei parametri di una funzione:

function stampa(valore: string | number) {
    console.log(valore);
}

Possiamo quindi chiamare la funzione stampa() con entrambi i tipi:

stampa("Ciao");
stampa(100);

Unione di più tipi

Un'unione può contenere più di due alternative. Ad esempio, possiamo specificarne tre:

let valore: string | number | boolean;

Ora valore può essere una string, un number o un boolean:

valore = "Ciao";
valore = 10;
valore = true;

Controllare il tipo di un'unione

Quando una variabile può avere più tipi, TypeScript non può presumere quale di questi valori contenga in un determinato momento.

Prendiamo come esempio questa funzione:

function mostra(valore: string | number) {
    console.log(valore);
}

Se vogliamo utilizzare un metodo specifico delle stringhe, dobbiamo prima verificare il tipo:

function mostra(valore: string | number) {
    if (typeof valore === "string") {
        console.log(valore.toUpperCase());
    }
}

All'interno dell'if, TypeScript sa che valore è una string.

Possiamo gestire anche il caso numerico:

function mostra(valore: string | number) {
    if (typeof valore === "string") {
        console.log(valore.toUpperCase());
    } else {
        console.log(valore.toFixed(2));
    }
}

Questo processo viene chiamato, in gergo, Type Narrowing e permette a TypeScript di restringere progressivamente i possibili tipi di un'unione.

I tipi letterali

Un tipo letterale permette di specificare non soltanto il tipo di un valore, ma il valore esatto che è consentito utilizzare.

Ad esempio:

let direzione: "destra";

Questa variabile può contenere esclusivamente la stringa "destra":

direzione = "destra";

Questa assegnazione invece genera un errore:

direzione = "sinistra"; // Errore

Anche se "sinistra" è una string, non è il valore esatto previsto dal tipo.

Tipi letterali con i numeri

I tipi letterali possono essere utilizzati anche con i numeri. Ad esempio:

let risposta: 200;

L'unico valore ammesso è 200:

risposta = 200;
risposta = 300; // Errore

Possiamo utilizzare anche più valori numerici attraverso un'unione:

type Codice = 200 | 400 | 404 | 500;

const codiceValido: Codice = 404;
const codiceErrato: Codice = 403; // Errore

Tipi letterali con i booleani

Anche true e false possono essere utilizzati come tipi letterali:

let attivo: true;

attivo = true;
attivo = false; // Errore

Prova!Completa gli spazi vuoti con il testo appropriato.
// Permetti anche valori numerici nella funzione
function stampaCodice(valore: string | ) {
    console.log(valore);
}

stampaCodice(500);

Prova! Scegli l'opzione corretta tra quelle elencate.
function mostraDato(dato: string | number) {
    if (typeof dato === "______") {
        console.log(dato.toUpperCase());
    }
}