Що таке "conditional type"?
Що таке Conditional Type
Conditional Type (умовний тип) має загальну форму:
javascript
T extends U ? X : YЦе читається як:
"Якщо тип
Tсумісний (assignable) з типомU, то результатом буде типX, інакше - типY."
Найпростіший приклад
javascript
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"Як це працює
extendsу контексті conditional type - не "успадкування", а перевірка сумісності типів;- умова обчислюється на етапі компіляції;
- результат - інший тип.
Приклад з реальними типами
javascript
type ElementType<T> = T extends (infer U)[] ? U : T;
type A = ElementType<string[]>; // string
type B = ElementType<number[]>; // number
type C = ElementType<boolean>; // booleanТут використовується
infer U- оператор для видобування підтипу.
Використання з узагальненнями (generics)
Conditional types особливо потужні в дженериках:
javascript
type Response<T> = T extends Error ? "Failed" : "Success";
type A = Response<string>; // "Success"
type B = Response<Error>; // "Failed"Приклад: фільтрація типів
javascript
type NonNullable<T> = T extends null | undefined ? never : T;
type A = NonNullable<string | null | undefined>; // stringЦе реальна реалізація вбудованого
NonNullable.
Дистрибутивна поведінка
Conditional types поводяться по-різному, якщо T - це union.
Якщо T - об'єднання (A | B), TypeScript розподіляє умову на кожну частину:
javascript
type ToArray<T> = T extends any ? T[] : never;
type R = ToArray<string | number>;
// (string | number) розподіляється -> string[] | number[]Тобто:
javascript
ToArray<string | number> ≡ ToArray<string> | ToArray<number>Це називається distributive conditional type.
Щоб вимкнути розподіл
Можна загорнути тип у кортеж, щоб "зняти" дистрибутивність:
javascript
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
type R = ToArrayNonDist<string | number>;
// (string | number)[]Приклади зі стандартної бібліотеки
Багато вбудованих утиліт побудовані на conditional types:
| Utility | Реалізація | Що робить |
|---|---|---|
Exclude<T, U> | T extends U ? never : T | Прибирає з T усе, що сумісне з U |
Extract<T, U> | T extends U ? T : never | Залишає лише перетин T і U |
NonNullable<T> | T extends null | undefined ? never : T | Прибирає null і undefined |
ReturnType<T> | T extends (...args:any) => infer R ? R : any | Видобуває тип значення, що повертається |
InstanceType<T> | T extends new (...args:any) => infer R ? R : any | Видобуває тип екземпляра, що створюється |
Приклади з практики
Вибір типу, що повертається
javascript
type Result<T> = T extends true ? "OK" : "FAIL";
type A = Result<true>; // "OK"
type B = Result<false>; // "FAIL"Перевірка, чи є тип функцією
javascript
type IsFunction<T> = T extends (...args: any[]) => any ? true : false;
type A = IsFunction<() => void>; // true
type B = IsFunction<number>; // falseВидобування результату Promise
javascript
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type A = UnwrapPromise<Promise<string>>; // string
type B = UnwrapPromise<number>; // numberУмовна типізація параметрів
javascript
type ApiResponse<T> = T extends { error: any }
? { ok: false; error: T["error"] }
: { ok: true; data: T };
type A = ApiResponse<{ data: string }>; // { ok: true; data: { data: string } }
type B = ApiResponse<{ error: string }>; // { ok: false; error: string }Ключові концепції
| Термін | Пояснення |
|---|---|
extends | Перевіряє сумісність типів |
infer | Дозволяє видобувати вкладені типи |
| Дистрибутивність | Conditional-тип застосовується окремо до кожного члена union |
never | Використовується для "виключення" значень з union |
| "Type-level if" | Conditional types - спосіб описувати розгалуження логіки на рівні типів |
Підсумок
| Поняття | Опис |
|---|---|
| Conditional type | Тип, який обирається залежно від іншого типу |
| Синтаксис | T extends U ? X : Y |
| Коли використовувати | Коли тип залежить від форми/сумісності іншого типу |
| Ключові інструменти | extends, infer, never |
| Приклади | Exclude, Extract, ReturnType, NonNullable, InstanceType |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.