Conditional types — T extends U ? X : Y

~20 daq · TypeScript · Ilg'or Turlar

Tur qaytaradigan funksiya yozmoqchisiz — argument string bo'lsa string[], number bo'lsa number[]. Overload bilan ishlaydi, lekin 10 ta tur uchun 10 ta overload. Conditional type — turga qarab tur tanlash, if/else mantiqida.


Conditional type sintaksisi

T extends U ? X : Y

"Agar T U ga tayinlanishi mumkin bo'lsa — X, aks holda — Y":

type Yaxshilangan<T> = T extends string ? string[] : number[];

type A = Yaxshilangan<string>;  // string[]
type B = Yaxshilangan<number>;  // number[]
type C = Yaxshilangan<boolean>; // number[]

Amaliy — null olib tashlash

type NonNullable<T> = T extends null | undefined ? never : T;

type A = NonNullable<string | null>;    // string
type B = NonNullable<number | undefined>; // number
type C = NonNullable<null | undefined>;   // never

Distribütiv conditional type

Union turida conditional type har elementga alohida qo'llanadi:

type Qobiq<T> = T extends string ? `"${T}"` : T;

type A = Qobiq<"ali" | "vali" | 42>;
// `"ali"` | `"vali"` | 42
// — string larga qo'llanadi, 42 ga emas

Distribütivlikni o'chirish uchun tuple:

type Bitta<T> = [T] extends [string] ? "ha" : "yo'q";
type A = Bitta<string | number>; // "yo'q" — union distribütiv emas

Ichma-ich conditional

type TypeName<T> =
  T extends string   ? "string"   :
  T extends number   ? "number"   :
  T extends boolean  ? "boolean"  :
  T extends null     ? "null"     :
  T extends undefined ? "undefined" :
  "ob'ekt";

type A = TypeName<string>;  // "string"
type B = TypeName<42>;      // "number"
type C = TypeName<Date>;    // "ob'ekt"

Funksiyadan qaytish turini chiqarish

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

function soni(): number { return 1; }
type A = FunksiyaQaytishi<typeof soni>; // number

(infer keyingi darsda batafsil)


Tez-tez uchraydigan xatolar

Distribütivlik kutilmagan natija:

type Yalang<T> = T extends any[] ? T[number] : T;
type A = Yalang<string[] | number>; // string | number — ikkalasiga alohida

Union kirsa — har elementga alohida qo'llanadi.


Xulosa

// Asosiy
type Agar<T, U, Ha, Yoq> = T extends U ? Ha : Yoq;

// Keng ishlatiladiganlar
type IsString<T>    = T extends string ? true : false;
type NonNullable<T> = T extends null | undefined ? never : T;
type Unwrap<T>      = T extends Array<infer U> ? U : T;

// Distribütiv — union da har elementga alohida
type Qobiq<T> = T extends string ? `"${T}"` : T;
type A = Qobiq<"a" | 1>; // `"a"` | 1

Keyingi dars

47-dars: infer kalit so'zi — conditional type ichida tur chiqarish