> Использовал ли ты mapped types в TypeScript (TypeScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Арго

Стек: TypeScript

> Пример ответа

Короткий ответ

Да, я регулярно использую mapped types в TypeScript для трансформации существующих типов, создания условных типов на основе ключей объекта и обеспечения типобезопасности при работе с API и конфигурациями. Это ключевой инструмент для построения гибких, переиспользуемых типов без дублирования кода.

Подробное объяснение

Mapped types - это механизм TypeScript, позволяющий создавать новые типы на основе существующих путём итерации по их ключам. Синтаксически это выглядит как { [P in K]: T }, где K - это union ключей, а T - тип значения. На практике я использую их для:

  • Преобразования модификаторов: сделать все поля readonly, optional или required
  • Изменения типов значений: например, обернуть все поля в Promise или Nullable
  • Фильтрации ключей: создать тип только с определёнными ключами или исключить их
  • Создания условных типов: применить разную логику к разным полям на основе их исходного типа

В реальных проектах mapped types незаменимы при работе с формами (создание типов для значений, ошибок, touched), при типизации API-ответов (трансформация snake_case в camelCase), при построении state-менеджеров и конфигураций.

На практике

В production-коде я чаще всего применяю mapped types для:

  1. Типизации форм: создаю тип FormValues<T> где все поля становятся optional, и отдельно FormErrors<T> с теми же ключами, но значениями string | null
  2. API-клиентов: трансформирую тип ответа сервера в клиентский тип, меняя имена полей и типы значений
  3. Конфигураций: создаю тип, где все поля конфигурации становятся readonly и optional с дефолтными значениями
  4. Event-систем: типизирую обработчики событий, где ключи - названия событий, а значения - типы payload

Важно помнить про keyof, as для переименования ключей и conditional types внутри mapped types для сложной логики.

Пример кода

TYPESCRIPT
// Базовый mapped type - делаем все поля optional и nullable
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
// С фильтрацией ключей - только строковые поля
type StringFields<T> = {
[P in keyof T as T[P] extends string ? P : never]: T[P];
};
// С трансформацией имён - snake_case в camelCase
type SnakeToCamel<T> = {
[P in keyof T as P extends string
? P.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
: P]: T[P];
};
// Реальный пример - типизация формы
interface UserForm {
name: string;
email: string;
age: number;
}
type FormState<T> = {
[P in keyof T]: {
value: T[P];
error: string | null;
touched: boolean;
};
};
// Использование
type UserFormState = FormState<UserForm>;
// {
// name: { value: string; error: string | null; touched: boolean; };
// email: { value: string; error: string | null; touched: boolean; };
// age: { value: number; error: string | null; touched: boolean; };
// }

Как отвечать на собеседовании

Начни с чёткого определения mapped types и их синтаксиса. Затем приведи 2-3 конкретных примера из своего опыта, объяснив, какую проблему они решали. Покажи понимание продвинутых возможностей: использование as для переименования ключей, комбинацию с conditional types, работу с keyof и never. Упомяни, что mapped types - это compile-time конструкция, не влияющая на runtime. Заверши демонстрацией простого, но показательного примера кода.

Что проверяет интервьюер

  • Понимание синтаксиса и механики mapped types
  • Умение применять их для реальных задач, а не только для демонстрации
  • Знание продвинутых фич: as, conditional types, keyof, never
  • Способность объяснить trade-offs между гибкостью типов и сложностью чтения
  • Понимание, что mapped types работают на уровне типов и не генерируют код

Типичные ошибки

  • Путать mapped types с Record<Keys, Type> - Record создаёт тип с одинаковыми значениями, mapped types позволяют разную логику для каждого ключа
  • Забывать про keyof - без него mapped type не будет работать с произвольными типами
  • Использовать mapped types там, где достаточно простого интерфейса - избыточная сложность
  • Не учитывать, что mapped types могут сделать тип менее читаемым для других разработчиков
  • Пытаться использовать mapped types для runtime-логики - это только compile-time конструкция

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью