> Для чего используется infer в TypeScript (TypeScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Арго
Стек: TypeScript
> Пример ответа
Короткий ответ
infer - ключевое слово в условных типах TypeScript, которое позволяет выводить (извлекать) тип из другого типа в процессе сопоставления с образцом. Оно работает только внутри ветки extends условного типа и даёт доступ к внутренним типам, например, к типу элемента массива (T extends Array<infer U> ? U : never) или типу возвращаемого значения функции (T extends (...args: any[]) => infer R ? R : never). Это мощный инструмент для создания гибких утилитарных типов.
Подробное объяснение
infer - это механизм pattern matching на уровне типов. Он объявляет переменную типа в позиции, где TypeScript может автоматически вывести конкретный тип на основе переданного аргумента. Ключевое ограничение: infer может использоваться только в части extends условного типа, после ключевого слова infer идёт имя переменной типа, которая затем доступна в ветвях true/false.
Пример базового синтаксиса:
TYPESCRIPTtype ExtractArrayItem<T> = T extends Array<infer U> ? U : never;
Здесь infer U говорит TypeScript: "если T - массив, выведи тип его элементов и назови его U, затем используй U в результате". Если T не массив - возвращается never.
infer может быть вложенным, использоваться с rest параметрами, кортежами, функциями, промисами и другими сложными типами. Например, извлечение типа возвращаемого значения функции:
TYPESCRIPTtype ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
Важно: infer не может быть использован вне условного типа, и переменная типа, объявленная через infer, видна только в пределах данного условного типа.
На практике
infer активно используется в:
- утилитарных типах стандартной библиотеки TypeScript (
ReturnType,Parameters,ConstructorParameters,InstanceType); - создании собственных type helpers для работы с API, Redux, React props;
- извлечении типов из сложных структур (например, тип payload из Promise, тип элемента из Tuple, тип ключа из Record);
- реализации type-safe middleware, HOC, декораторов;
- построении discriminated unions и type guards на уровне типов.
Пример из реального проекта: извлечение типа данных из ответа API, обёрнутого в Promise:
TYPESCRIPTtype ApiResponse<T> = T extends Promise<infer U> ? U : T;
Пример кода
TYPESCRIPT// Извлечение типа элемента массиваtype ArrayItem<T> = T extends Array<infer U> ? U : never;type Test1 = ArrayItem<string[]>; // stringtype Test2 = ArrayItem<number[]>; // numbertype Test3 = ArrayItem<boolean>; // never// Извлечение типа возвращаемого значения функцииtype MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;type Test4 = MyReturnType<() => string>; // stringtype Test5 = MyReturnType<(a: number) => boolean>; // boolean// Извлечение типа из Promisetype UnwrapPromise<T> = T extends Promise<infer U> ? U : T;type Test6 = UnwrapPromise<Promise<string>>; // stringtype Test7 = UnwrapPromise<number>; // number// Извлечение первого элемента кортежаtype First<T extends any[]> = T extends [infer F, ...any[]] ? F : never;type Test8 = First<[1, 2, 3]>; // 1type Test9 = First<[]>; // never// Вложенный infer: извлечение типа из вложенного Promisetype DeepUnwrap<T> = T extends Promise<infer U> ? DeepUnwrap<U> : T;type Test10 = DeepUnwrap<Promise<Promise<string>>>; // string
Как отвечать на собеседовании
Начни с чёткого определения: infer - это ключевое слово для вывода типа внутри условного типа. Приведи простой пример с массивом или функцией. Объясни ограничения (только в extends, только одна позиция на один infer). Покажи практическое применение: ReturnType, Parameters, собственные утилиты. Если спросят про сложные случаи - расскажи про инвариантность, ковариантность и контрвариантность в контексте infer (например, почему infer в параметрах функции работает контрвариантно). Упомяни, что infer - это основа для построения type-level programming в TypeScript.
Что проверяет интервьюер
- Понимание условных типов и pattern matching на уровне типов.
- Умение читать и писать сложные type helpers.
- Знание стандартных утилитарных типов и их реализации.
- Понимание ограничений
infer(только вextends, область видимости). - Способность объяснить, как TypeScript выводит типы в разных контекстах (функции, массивы, промисы).
- Глубокое понимание системы типов TypeScript (вариантность, распределительные условные типы).
Типичные ошибки
- Использование
inferвне условного типа (синтаксическая ошибка). - Попытка использовать
inferв нескольких позициях без необходимости (можно, но нужно понимать порядок вывода). - Путаница между
inferиtypeof-inferработает на уровне типов,typeof- на уровне значений. - Неправильное понимание области видимости: переменная
inferдоступна только в веткахtrue/falseданного условного типа. - Игнорирование распределительного поведения условных типов с union (например,
ArrayItem<string | number[]>дастstring | number, а неstring | number[]). - Попытка вывести тип, который не может быть выведен из-за инвариантности (например,
Set<T>-inferне сработает, так какSetинвариантен поT).
> Похожие задачи по frontend
Что такое public в TypeScript?
Что значит опциональное поле в TypeScript
Использовал ли ты mapped types в TypeScript
Используешь ли условные типы (conditional types) в TypeScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью