Saltar al contenido principal
eLearner.app
Módulo 2 · Lección 2 de 24/14 en el curso~15 min
Lecciones del módulo (2/2)

Unioni e Restringimento

Nel mondo reale, le variabili e le risposte delle API non hanno sempre un singolo tipo fisso. TypeScript offre i Tipi Unione (Union Types) per gestire la variabilità, e il Restringimento dei Tipi (Type Narrowing) per operare in sicurezza su di essi a runtime.


Tipi Unione (Union Types)

Un tipo unione permette a una variabile di accettare valori di tipi differenti. Viene espresso tramite il simbolo della barra verticale (|):

TS
let result: number | string;
result = 42; // Valido
result = 'Errore 404'; // Valido

Tuttavia, quando lavoriamo con un tipo unione, non possiamo chiamare direttamente metodi che appartengono a uno solo dei tipi (ad esempio, non possiamo fare .toUpperCase() se la variabile può anche essere un number). Dobbiamo prima "restringere" il tipo.


Restringimento dei Tipi (Type Narrowing)

Il Type Narrowing è il processo con cui TypeScript analizza le strutture di controllo del flusso (come if o switch) per dedurre un tipo più specifico per una variabile a runtime.

Esistono diversi modi per effettuare il narrowing:

1. Operatore typeof

Ideale per distinguere i tipi primitivi:

TS
function printLength(value: string | number) {
  if (typeof value === 'string') {
    // Qui TypeScript sa che 'value' è una stringa
    console.log(value.length);
  } else {
    // Qui TypeScript sa che 'value' è un numero
    console.log(value.toFixed(2));
  }
}

2. Operatore in

Utilizzato per verificare la presenza di una proprietà specifica in un oggetto:

TS
interface Fish {
  swim: () => void;
}
interface Bird {
  fly: () => void;
}

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    animal.swim(); // Narrowing a Fish
  } else {
    animal.fly(); // Narrowing a Bird
  }
}

Unioni Discriminate (Discriminated Unions)

Il pattern delle Unioni Discriminate consiste nel creare oggetti che condividono una proprietà comune con un valore letterale univoco (chiamata discriminatore). TypeScript riconosce questo discriminatore ed effettua il narrowing automatico all'interno di blocchi condizionali.

TS
interface SuccessResponse {
  status: 'success'; // Discriminatore letterale
  data: string;
}

interface ErrorResponse {
  status: 'error'; // Discriminatore letterale
  errorMessage: string;
}

type ApiResponse = SuccessResponse | ErrorResponse;

function handleResponse(response: ApiResponse) {
  if (response.status === 'success') {
    console.log('Dati ricevuti:', response.data);
  } else {
    console.error('Si è verificato un errore:', response.errorMessage);
  }
}

Prova tu

Esercizio 1: Unione di Tipi

Ejercicio#ts.m2.l2.e1
Intentos: 0Cargando...

Dichiara una variabile chiamata id che può essere sia un numero che una stringa. Inizializzala prima con il numero 101, poi assegna il valore stringa 'USER-101'.

Cargando editor...
Mostrar pista

Usa l'operatore | per unire number e string nella dichiarazione della variabile let.

Solución disponible después de 3 intentos

Esercizio 2: Type Narrowing Base

Ejercicio#ts.m2.l2.e2
Intentos: 0Cargando...

Crea una funzione chiamata formatInput che accetta un parametro input di tipo stringa o numero. Se input è una stringa, restituisci input convertito in maiuscolo. Se è un numero, restituisci input moltiplicato per 2. Specifica i tipi in modo esplicito.

Cargando editor...
Mostrar pista

Usa typeof input === 'string' all'interno di un blocco if per distinguere il comportamento.

Solución disponible después de 3 intentos

Esercizio 3: Narrowing con 'in'

Ejercicio#ts.m2.l2.e3
Intentos: 0Cargando...

Date le due interfacce Car (con metodo drive) e Boat (con metodo sail), scrivi una funzione chiamata moveVehicle che accetta un parametro vehicle di tipo Car o Boat. Se vehicle ha la proprietà drive, esegui il metodo drive(). Altrimenti, esegui il metodo sail().

Cargando editor...
Mostrar pista

Usa l'operatore in nella forma 'drive' in vehicle per fare il narrowing dell'interfaccia.

Solución disponible después de 3 intentos

Esercizio 4: Unione Discriminata Shape

Ejercicio#ts.m2.l2.e4
Intentos: 0Cargando...

Definisci un tipo Shape che è l'unione di due tipi: Circle e Square. Circle ha una proprietà kind impostata su 'circle' (valore letterale) e un radius (numero). Square ha una proprietà kind impostata su 'square' (valore letterale) e un side (numero). Scrivi poi una funzione getArea che accetta shape di tipo Shape e restituisce l'area come numero (per il cerchio Math.PI * radius * radius, per il quadrato side * side).

Cargando editor...
Mostrar pista

Usa shape.kind === 'circle' all'interno di getArea per discriminare il tipo e calcolare l'area corretta.

Solución disponible después de 3 intentos