ProgrammazioneArchitetto TypeScript

Как работает conditional types (условные типы) в TypeScript? Что такое дистрибутивное поведение условных типов и как с ним работают? Поясните на примерах.

Supera i colloqui con l'assistente IA Hintsage

Ответ.

I tipi condizionali (conditional types) in TypeScript consentono di descrivere un tipo attraverso un altro secondo il principio T extends U ? X : Y. Questi tipi offrono potenti possibilità nella costruzione di logiche di tipo complesse, specialmente nelle librerie e nelle dichiarazioni API.

Esempio di tipo condizionale di base:

type IsString<T> = T extends string ? 'yes' : 'no'; type A = IsString<string>; // 'yes' type B = IsString<number>; // 'no'

Comportamento distribuitivo

Se un tipo condizionale viene applicato a un tipo union, TypeScript "distribuisce" la condizione su ciascun elemento dell'unione separatamente. Questo è chiamato comportamento distribuitivo dei tipi condizionali.

Esempio:

type Foo<T> = T extends { id: number } ? string : boolean; type Result = Foo<{id: number} | {name: string}>; // string | boolean

Questa è una caratteristica molto potente, ma può causare confusione con il risultato atteso, specialmente quando si lavora con array e mappatura dei tipi.

Come evitare il comportamento distribuitivo

Avvolgiamo il tipo in una tupla:

type NoDistrib<T> = [T] extends [{id: number}] ? string : boolean; type Result = NoDistrib<{id: number} | {name: string}>; // boolean

Domanda trabocchetto.

Domanda: "Cosa succede se si usa un tipo condizionale con tipi union senza avvolgerli in tuple? Il risultato è sempre lo stesso che nella logica normale?"

Risposta: Il risultato può essere inaspettato! A causa della distribuzione, la condizione viene applicata a ciascun membro dei tipi union separatamente. Per confrontare rigorosamente l'intero tipo union, è necessario utilizzare un involucro (tupla).

Esempio:

type Test<T> = T extends string ? number : boolean; type A = Test<string | boolean>; // number | boolean, non solo boolean

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze dell'argomento.


Storia

Nella libreria per la serializzazione è stato utilizzato un tipo condizionale per controllare la struttura dei dati, ma ci si è dimenticati di avvolgere il parametro generico in una tupla. Di conseguenza, sulle dichiarazioni di tipi union complessi si sono rotte, e il compilatore ha restituito tipi imprevedibili nell'uso dell'API.


Storia

Nel tentativo di implementare una trasformazione di tipo per la gestione dei campi dei modelli, si è verificata la perdita di parte delle informazioni: a causa del fatto che la distribuzione genera unioni, alcune ramificazioni della logica sono state dimenticate, risultando in una tipizzazione troppo permissiva.


Storia

Un sviluppatore pensava che T extends SomeType all'interno dei tipi condizionali si comportasse come ci si aspetta per l'intero oggetto, ma si è verificata una "disperazione" — il compilatore ha segnalato incoerenze, e sono iniziati il tipo caos e gravi bug nella generazione della documentazione automatica.