Що означає infer у TypeScript?
Синтаксис
javascript
T extends SomeType<infer U> ? U : DefaultTypeinfer U- це оголошення нового типуU, який TypeScript спробує вивести з типуT, якщоTвідповідає шаблонуSomeType<...>.- Якщо вивести можна - повертається
U. - Якщо не можна - використовується гілка після
:.
Приклад 1: Видобування типу з Promise
javascript
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type A = UnwrapPromise<Promise<string>>; // string
type B = UnwrapPromise<number>; // numberТут
infer Uкаже: "якщоT- цеPromise<X>, виведиX".
Приклад 2: Видобування типу елементів масиву
javascript
type ElementType<T> = T extends (infer U)[] ? U : T;
type A = ElementType<string[]>; // string
type B = ElementType<number[]>; // number
type C = ElementType<boolean>; // booleaninfer U дозволяє "розпакувати" тип елементів масиву.
Приклад 3: Видобування типу аргументів функції
javascript
type ArgType<T> = T extends (arg: infer U) => any ? U : never;
type A = ArgType<(x: number) => void>; // number
type B = ArgType<(x: string) => void>; // stringЯкщо
T- функція,infer Uвитягує тип її аргументу.
Приклад 4: Видобування типу, що повертається функцією
javascript
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
type A = ReturnTypeOf<() => string>; // string
type B = ReturnTypeOf<(x: number) => boolean>; // booleanСаме так реалізовано вбудований утилітний тип
ReturnType<T>у TypeScript.
Приклад 5: Множинні infer-виведення
javascript
type FirstArgAndReturn<T> =
T extends (arg: infer A) => infer R ? [A, R] : never;
type Example = (x: string) => number;
type Result = FirstArgAndReturn<Example>; // [string, number]Приклад 6: Видобування типів з кортежів
javascript
type First<T> = T extends [infer F, ...any[]] ? F : never;
type Last<T> = T extends [...any[], infer L] ? L : never;
type A = First<[1, 2, 3]>; // 1
type B = Last<[1, 2, 3]>; // 3Приклад 7: Розпакування вкладених типів (nested generics)
javascript
type DeepUnwrap<T> =
T extends Promise<infer U> ? DeepUnwrap<U> : T;
type A = DeepUnwrap<Promise<Promise<string>>>; // stringЯк це працює логічно
infer діє всередині умовного типу:
- Перевіряє, чи відповідає
Tпевній структурі (extends Pattern). - Якщо так, TypeScript "підставляє" конкретні типи замість
infer U. - Ці виведені типи можна використовувати в правій частині виразу (
? ... : ...).
Важливі обмеження
inferпрацює лише всерединіextends(не можна використовувати окремо).- Можна оголошувати кілька
infer-змінних. - TypeScript може вивести об'єднання типів, якщо умова підходить під кілька форм.
ПІДСУМОК
| Що робить | Приклад | Результат |
|---|---|---|
Видобуває тип з Promise | T extends Promise<infer U> ? U : T | "розпаковує" проміс |
| Видобуває елемент масиву | T extends (infer U)[] ? U : T | отримує тип елементів |
| Видобуває аргумент функції | T extends (arg: infer A) => any ? A : never | отримує тип аргументу |
| Видобуває значення, що повертається | T extends (...args: any[]) => infer R ? R : never | отримує тип результату |
| Видобуває з кортежу | T extends [infer F, ...any[]] ? F : never | перший елемент |
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.