Ce face conditional types
Un tip condițional seamănă cu operatorul ? :, dar pentru tipuri: T extends string ? "text" : "altceva" dă "text" dacă T se potrivește cu string și "altceva" în rest. Este folosit aproape mereu cu un generic, pentru a calcula un tip din altul.
Când T este un union, condiția se aplică pe fiecare variantă separat și rezultatele se unesc (tip condițional distributiv). Așa funcționează Exclude: T extends U ? never : T elimină variantele care se potrivesc. Ca să tratezi union-ul ca întreg, pune ambele părți în paranteze pătrate: [T] extends [U].
Cu infer poți extrage o parte dintr-un tip în interiorul condiției (tipul elementelor unui tablou, rezultatul unei funcții). Multe tipuri utilitare sunt tipuri condiționale: Exclude, Extract, NonNullable, ReturnType, Awaited.
Exemple
Exemplul 1: Tip care depinde de argument
Pentru un id numeric, funcția returnează un number; pentru un text, un string. Conversia as din implementare este necesară, pentru că tsc nu poate verifica singur ramurile.
type Normalizat<T> = T extends string ? string : number;
function normalizeaza<T extends string | number>(id: T): Normalizat<T> {
return (typeof id === "string" ? id.trim().toUpperCase() : Math.trunc(id)) as Normalizat<T>;
}
const a = normalizeaza(" ro-7 "); // string
const b = normalizeaza(42.9); // number
console.log(a, a.length, b, b.toFixed(1));
Rezultat
RO-7 4 42 42.0
Exemplul 2: Distribuție pe union
Condiția se aplică pe fiecare variantă: string și number trec, boolean devine never și dispare.
type DoarTextSauNumar<T> = T extends string | number ? T : never;
type Rezultat = DoarTextSauNumar<string | number | boolean>; // string | number
type CaTablou<T> = T extends unknown ? T[] : never;
type Tablouri = CaTablou<string | number>; // string[] | number[]
const x: Rezultat = "Iași";
const t: Tablouri = [1, 2, 3];
console.log(x, t);
Rezultat
Iași [ 1, 2, 3 ]
Exemplul 3: Valoarea nu se potrivește cu ramura aleasă
EsteTablou<number> este false, deci valoarea true nu se potrivește.
type EsteTablou<T> = T extends unknown[] ? true : false;
const a: EsteTablou<string[]> = true;
const b: EsteTablou<number> = true;
console.log(a, b);
Eroarea afișată de tsc
exemplu.mts(3,7): error TS2322: Type 'true' is not assignable to type 'false'.
Greșeli frecvente
- Te miri că
EsteNever<never>scris caT extends never ? true : falsedănever. Un union gol se distribuie în nimic; scrie[T] extends [never]. - Construiești tipuri condiționale foarte adânci. Erorile devin greu de citit; păstrează-le scurte și dă-le nume.
Comenzi înrudite
infer: În ramura extends a unui tip condițional, infer X „prinde” o parte din tip și o dă un nume.Exclude: Exclude<T, U> elimină din union-ul T variantele care se potrivesc cu U.Extract: Extract<T, U> păstrează din union-ul T doar variantele care se potrivesc cu U.mapped types: Construiesc un tip nou trecând prin fiecare cheie a altui tip: { [K in keyof T]: … }.generics (<T>): Parametri de tip: o funcție sau clasă scrisă o dată, care funcționează cu orice tip și păstrează tipul exact.