Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що означає infer у TypeScript?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`infer U`** - це оголошення нового типу `U`, який TypeScript намагається **вивести** з типу `T`, якщо `T` відповідає шаблону `SomeType<...>`. **Ключове:** якщо вивести можна - повертається `U`, якщо ні - використовується гілка після `:`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Синтаксис ```javascript T extends SomeType<infer U> ? U : DefaultType ``` - `infer 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>; // boolean ``` `infer 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`. - Ці виведені типи можна використовувати в правій частині виразу (`? ... : ...`). --- ## Важливі обмеження 1. `infer` **працює лише всередині** `extends` (не можна використовувати окремо). 2. Можна оголошувати **кілька** `infer`-змінних. 3. 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` | перший елемент |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.