> Какие альтернативы использованию infer в TypeScript для типизации ключей? (TypeScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: RecruitTech
Стек: TypeScript
> Пример ответа
Короткий ответ
infer в TypeScript используется для извлечения типов из условных типов. Для типизации ключей без infer можно использовать keyof, mapped types с in и as, а также Extract и Exclude для фильтрации ключей. Для работы с значениями по ключам подойдут Indexed Access Types (T[K]). infer незаменим только при необходимости вывести тип из сложной структуры, например, из типа функции или Promise.
Подробное объяснение
infer - это мощный инструмент для вывода типов внутри условных типов, но для типизации ключей часто можно обойтись без него. Основные альтернативы:
-
keyof- получает объединение всех ключей объекта:TYPESCRIPTtype Keys = keyof { a: number; b: string }; // 'a' | 'b' -
Mapped types с
inиas- позволяют трансформировать ключи:TYPESCRIPTtype Prefixed<T> = { [K in keyof T as `prefix_${string & K}`]: T[K] } -
ExtractиExclude- фильтруют ключи по условию:TYPESCRIPTtype StringKeys<T> = Extract<keyof T, string> -
Indexed Access Types - получают тип значения по ключу:
TYPESCRIPTtype Value = SomeType['key'] -
Conditional types с проверкой extends - для сложной логики без
infer:TYPESCRIPTtype IsStringKey<T, K> = K extends keyof T ? (T[K] extends string ? K : never) : never
infer становится необходимым, когда нужно извлечь внутренний тип из обёртки (например, тип элемента массива из Array<T> или возвращаемый тип функции).
На практике
Для типизации ключей в реальных проектах чаще всего достаточно комбинации keyof и mapped types. infer обычно применяется в библиотечных утилитах (типа ReturnType, Parameters) или при работе с дженериками высшего порядка.
Примеры практического использования без infer:
- Получение всех строковых ключей:
type StringKeys<T> = Extract<keyof T, string> - Создание типа с префиксами ключей:
type PrefixedKeys<T> = { [K in keyof T asget${Capitalize<string & K>}]: T[K] } - Фильтрация ключей по типу значения:
type NumericKeys<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T]
Пример кода
TYPESCRIPTinterface User {id: number;name: string;email: string;age: number;}// Без infer: получаем ключи со строковыми значениямиtype StringValueKeys<T> = {[K in keyof T]: T[K] extends string ? K : never}[keyof T];type UserStringKeys = StringValueKeys<User>; // "name" | "email"// С infer: аналогичный результат, но с избыточным использованием infertype StringValueKeysWithInfer<T> = T extends { [K in keyof T]: infer V }? { [K in keyof T]: V extends string ? K : never }[keyof T]: never;// Более сложный пример: получение ключей, где значение - массивtype ArrayKeys<T> = {[K in keyof T]: T[K] extends any[] ? K : never}[keyof T];type UserArrayKeys = ArrayKeys<User>; // never (в User нет массивов)
Как отвечать на собеседовании
Начните с чёткого разделения: infer - для вывода типов из сложных структур, а для работы с ключами есть специализированные инструменты. Приведите 2-3 альтернативы с примерами. Подчеркните, что infer не является основным инструментом для типизации ключей - это скорее исключение для продвинутых сценариев. Упомяните trade-off: infer делает код менее читаемым, поэтому его стоит использовать только когда другие подходы не работают.
Что проверяет интервьюер
- Понимание разницы между выводом типов (
infer) и прямым доступом к ключам (keyof) - Знание mapped types и условных типов
- Умение выбирать правильный инструмент под задачу
- Понимание, когда
inferдействительно необходим, а когда это избыточно - Способность объяснить trade-off между выразительностью и читаемостью кода
Типичные ошибки
- Попытка использовать
inferтам, где достаточноkeyofили mapped types - Непонимание, что
inferработает только внутри conditional types сextends - Использование
inferдля простых случаев, что усложняет код без необходимости - Путаница между
inferдля ключей иinferдля значений - Игнорирование встроенных утилит (Extract, Exclude) в пользу ручных конструкций с infer
> Похожие задачи по frontend
Как типизировать объект с разными ключами и значениями в TypeScript?
Можно ли объединить несколько типов в один тип в TypeScript и как это сделать?
Что такое Record в TypeScript и как его использовать?
Что такое Pick в TypeScript и как его использовать?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью