Conditional Types
TypeScript-д нөхцлөөс хамааран өөр өөр төрөл буцаах боломжтой. Энэ онцлогийг conditional type гэдэг бөгөөд үүний синтакс нь JavaScript-ийн тернар оператортай (? :) ижил харагдана.
Үндсэн синтакс
T extends U ? X : Y
"Хэрэв T нь U-г өргөтгөж байвал X төрлийг буцаа, үгүй бол Y төрлийг буцаа" гэсэн утгатай:
// Энгийн жишээ
type МөрЭсэх<T> = T extends string ? true : false;
type Тест1 = МөрЭсэх<string>; // true
type Тест2 = МөрЭсэх<number>; // false
type Тест3 = МөрЭсэх<"Монгол">; // true — string literal мөн string-г өргөтгөнө
// Тоо эсэхийг шалгах
type ТооЭсэх<T> = T extends number ? "тоо" : "тоо биш";
type Ш1 = ТооЭсэх<42>; // "тоо"
type Ш2 = ТооЭсэх<"hello">; // "тоо биш"
type Ш3 = ТооЭсэх<boolean>; // "тоо биш"
Conditional type-г функцтэй хослуулах
Conditional type нь generic-тэй хослуулах үед хамгийн хүчтэй болдог:
// Массив бол элементийн төрлийг, үгүй бол тухайн төрлийг буцаана
type МассивНь<T> = T extends (infer Item)[] ? Item : T;
type Тест1 = МассивНь<string[]>; // string
type Тест2 = МассивНь<number[]>; // number
type Тест3 = МассивНь<boolean>; // boolean — массив биш тул өөрийгөө буцаана
// Promise бол дотоод төрлийг задлах
type PromiseНь<T> = T extends Promise<infer R> ? R : T;
type Тест4 = PromiseНь<Promise<string>>; // string
type Тест5 = PromiseНь<Promise<number>>; // number
type Тест6 = PromiseНь<boolean>; // boolean
Distributive conditional types
Union төрлөөр T дамжуулахад conditional type тус тусдаа хэрэглэгддэг:
type НullГүй<T> = T extends null | undefined ? never : T;
type Тест1 = НullГүй<string | null | undefined>;
// string — null ба undefined хасагдаж string л үлдэнэ
type Тест2 = НullГүй<number | null>;
// number
// Яаж ажилладагыг задалж харвал:
// НullГүй<string | null | undefined>
// = НullГүй<string> | НullГүй<null> | НullГүй<undefined>
// = string | never | never
// = string
never нь union-д нэмэгдэхэд автоматаар хасагддаг — тиймээс string | never гэдэг нь зүгээр string болдог.
Бодит жишээ: функцийн буцаах төрлийг авах
// Функц бол буцаах төрлийг, үгүй бол never буцаана
type БуцаахТөрөл<T> = T extends (...args: any[]) => infer R ? R : never;
function нэмэх(а: number, б: number): number {
return а + б;
}
function мэндчилэх(нэр: string): string {
return `Сайн уу, ${нэр}!`;
}
type Нэмэхийн_буцаалт = БуцаахТөрөл<typeof нэмэх>; // number
type Мэндчилэхийн_буцаалт = БуцаахТөрөл<typeof мэндчилэх>; // string
// TypeScript-д суурилсан ReturnType<T> яг ингэж бичигдсэн
type МорьТестлэх = ReturnType<typeof нэмэх>; // number
Nested conditional type
Conditional type-г давхарлаж болно — JavaScript-ийн if...else if...else шиг:
type ТөрлийнНэр<T> = T extends string
? "string"
: T extends number
? "number"
: T extends boolean
? "boolean"
: T extends null
? "null"
: T extends undefined
? "undefined"
: "object";
type Тест1 = ТөрлийнНэр<"Монгол">; // "string"
type Тест2 = ТөрлийнНэр<42>; // "number"
type Тест3 = ТөрлийнНэр<true>; // "boolean"
type Тест4 = ТөрлийнНэр<null>; // "null"
type Тест5 = ТөрлийнНэр<{}>; // "object"
Conditional type нь TypeScript-ийн хамгийн нарийн онцлогуудын нэг. Эхлээд ойлгоход хэцүү мэт санагдаж болох ч хэрэглэж дадсанаар кодын илэрхийлэх чадвар эрс нэмэгдэнэ.
Дараагийн хичээлд:
Template Literal Types — мөрийн загвар дээр суурилсан шинэ төрлүүдийг хэрхэн үүсгэх, property нэрийг автоматаар хувиргахыг сурна.