> Используешь ли условные типы (conditional types) в TypeScript (TypeScript)

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

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

Стек: TypeScript

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

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

Да, регулярно использую условные типы для создания гибких и типобезопасных абстракций. Они позволяют выводить типы на основе условий, что особенно полезно при работе с перегрузками функций, discriminated unions и трансформациями типов. Основные сценарии: извлечение типов из сложных структур, создание type-safe API для библиотек и реализация паттернов вроде infer для вывода внутренних типов.

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

Условные типы в TypeScript - это мощный инструмент для построения типов, зависящих от других типов. Они работают по принципу тернарного оператора: T extends U ? X : Y. Ключевая особенность - дистрибутивность: если T - union, условие применяется к каждому элементу union отдельно.

На практике я использую их для:

  • Извлечения типов из сложных структур через infer (например, ReturnType<T>, Parameters<T>)
  • Создания discriminated type guards без runtime-кода
  • Построения type-safe middleware и HOC в React
  • Реализации conditional return types для перегруженных функций
  • Трансформации типов (например, NonNullable<T>, Exclude<T, U>)

Важно понимать trade-off: чрезмерное использование условных типов может усложнить читаемость и замедлить компиляцию. Оптимальный подход - применять их для публичных API библиотек и сложных generic-абстракций, избегая в простых утилитах.

На практике

В реальных проектах условные типы незаменимы при работе с:

  • API-клиентами: автоматическое определение типов ответов на основе параметров запроса
  • State management: типизация редьюсеров с discriminated actions
  • React-компонентами: создание пропсов, зависящих от других пропсов (conditional props)
  • Utility types: кастомные утилиты вроде DeepPartial<T>, PickByValue<T, V>

Типичный сценарий - создание type-safe функции, которая принимает разные типы и возвращает соответствующий результат без использования any. Например, функция для работы с localStorage, где тип возвращаемого значения зависит от переданного default-значения.

Пример кода

TYPESCRIPT
// Извлечение типа из Promise
type Unwrap<T> = T extends Promise<infer U> ? U : T;
type Result = Unwrap<Promise<string>>; // string
// Conditional return type для функции
function getConfig<T extends boolean>(
withDefaults: T
): T extends true ? { theme: string; lang: string } : { theme?: string; lang?: string } {
return withDefaults
? { theme: 'light', lang: 'en' } as any
: {} as any;
}
// Discriminated union с условными типами
type Event =
| { type: 'click'; x: number; y: number }
| { type: 'keypress'; key: string };
type EventHandler<T extends Event['type']> =
T extends 'click'
? (event: { x: number; y: number }) => void
: T extends 'keypress'
? (event: { key: string }) => void
: never;
// Utility type с infer
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? DeepReadonly<T[K]>
: T[K];
};

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

Начни с конкретного примера использования в реальном проекте, затем объясни механизм работы. Покажи понимание дистрибутивности и infer. Упомяни, когда условные типы избыточны (например, для простых маппингов лучше использовать mapped types). Хорошо продемонстрировать знание встроенных условных типов (ReturnType, InstanceType) и умение создавать кастомные.

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

  • Понимание системы типов TypeScript на продвинутом уровне
  • Умение проектировать гибкие и безопасные API
  • Знание trade-off между сложностью типов и читаемостью кода
  • Способность применять абстрактные концепции к реальным задачам
  • Понимание внутренних механизмов TypeScript (дистрибутивность, infer, conditional chains)

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

  • Забывают про дистрибутивность условных типов для union-типов
  • Используют условные типы там, где достаточно простого generic или overload
  • Создают бесконечную рекурсию через условные типы без базового случая
  • Путают extends в условных типах с наследованием классов
  • Чрезмерно усложняют типы, делая код нечитаемым для других разработчиков
  • Не учитывают производительность: сложные цепочки условных типов замедляют компиляцию

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

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