Tipi condizionali TypeScript

I tipi condizionali in TypeScript forniscono un modo per creare tipi che dipendono da una condizione. Consentono una maggiore flessibilità ed espressività nelle definizioni di tipo, rendendo possibile modellare relazioni di tipo complesse in modo chiaro e conciso. Questo articolo esplora il funzionamento dei tipi condizionali in TypeScript e fornisce esempi per illustrarne l'uso.

Cosa sono i tipi condizionali?

I tipi condizionali consentono la creazione di tipi selezionati in base a una condizione. Sono simili alle istruzioni condizionali nella programmazione, ma operano a livello di tipo. La sintassi di base di un tipo condizionale è:

type ConditionalType = T extends U ? X : Y;

In questa sintassi:

  • T è il tipo controllato.
  • U è il tipo con cui effettuare il confronto.
  • X è il tipo restituito se T estende U.
  • Y è il tipo restituito se T non estende U.

Esempio di base di tipi condizionali

Ecco un semplice esempio di un tipo condizionale che restituisce tipi diversi a seconda che un dato tipo sia una stringa o meno:

type IsString = T extends string ? "String" : "Not a string";

type Result1 = IsString;  // Result1 is "String"
type Result2 = IsString;  // Result2 is "Not a string"

In questo esempio, IsString controlla se T estende string. In tal caso, il risultato è "String"; in caso contrario, è "Not a string".

Utilizzo di tipi condizionali con tipi generici

I tipi condizionali possono anche essere usati con tipi generici per creare definizioni di tipo più flessibili e riutilizzabili. Ad esempio, un tipo che estrae il tipo di ritorno di una funzione:

type ReturnType = T extends (...args: any[]) => infer R ? R : never;

type FunctionType = (x: number) => string;

type Result = ReturnType;  // Result is string

In questo esempio, ReturnType usa la parola chiave infer per dedurre il tipo di ritorno R del tipo di funzione T. Se T è un tipo di funzione, ReturnType sarà il tipo di ritorno; altrimenti, il valore predefinito è never.

Tipi condizionali con tipi unione

I tipi condizionali possono anche funzionare con i tipi union per gestire più tipi possibili. Ad esempio, distinguendo tra diversi membri union:

type ExtractString = T extends string ? T : never;

type UnionType = string | number | boolean;

type Result = ExtractString;  // Result is string

In questo esempio, ExtractString estrae string da un tipo unione UnionType, ottenendo string.

Tipi condizionali con mapping dei tipi

I tipi condizionali possono essere combinati con i mapping dei tipi per creare trasformazioni di tipo più complesse. Ad esempio, il mapping su un array di tipi per applicare un tipo condizionale:

type MapArray = {
  [K in keyof T]: T[K] extends string ? T[K] : never;
};

type ArrayType = [string, number, boolean];

type MappedArray = MapArray;  // MappedArray is [string, never, never]

In questo esempio, MapArray mappa ogni elemento dell'array T e applica un tipo condizionale a ogni elemento, creando un array in cui vengono conservati solo gli elementi stringa.

Conclusione

I tipi condizionali in TypeScript sono uno strumento potente per creare definizioni di tipo flessibili ed espressive. Sfruttando i tipi condizionali, gli sviluppatori possono modellare relazioni di tipo complesse, gestire vari scenari e migliorare la sicurezza dei tipi nel loro codice TypeScript. Capire come usare i tipi condizionali in modo efficace può migliorare significativamente la capacità di scrivere codice TypeScript robusto e gestibile.