> Можно ли объединить несколько типов в один тип в TypeScript и как это сделать? (TypeScript)

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

Компании: Инрэко, The Tribe

Стек: TypeScript

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

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

Да, в TypeScript можно объединить несколько типов в один с помощью union types (|) и intersection types (&). Union type создаёт тип, который может быть одним из перечисленных, а intersection - тип, объединяющий все свойства исходных типов. Для сложных комбинаций используются mapped types, conditional types и utility types вроде Partial, Pick и Omit.

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

Union types (|) позволяют переменной принимать значения любого из указанных типов. Например, string | number - значение может быть строкой или числом. Intersection types (&) создают тип, содержащий все свойства объединяемых типов: TypeA & TypeB требует наличия всех полей из обоих типов.

Для более гибкого объединения используются:

  • Discriminated unions - union типов с общим полем-дискриминатором для type narrowing
  • Mapped types - создание новых типов на основе существующих через in keyof
  • Conditional types - T extends U ? X : Y для выбора типа на основе условия
  • Utility types - Partial<T>, Required<T>, Readonly<T>, Pick<T, K>, Omit<T, K>

Intersection types особенно полезны для миксинов и комбинирования интерфейсов, но могут привести к конфликтам при пересечении одинаковых полей с разными типами.

На практике

Union types часто используются для:

  • Обработки разных форм данных в API (например, SuccessResponse | ErrorResponse)
  • Типизации состояний в state management (loading, success, error)
  • Работы с optional значениями (T | null | undefined)

Intersection types применяются для:

  • Комбинирования нескольких интерфейсов в один тип
  • Расширения типов без наследования классов
  • Создания типов для mixins в функциональном стиле

Discriminated unions - стандартный паттерн для типизации Redux actions, где поле type служит дискриминатором.

Пример кода

TYPESCRIPT
// Union type
type Status = 'idle' | 'loading' | 'success' | 'error';
// Intersection type
type WithId = { id: number };
type WithTimestamp = { createdAt: Date };
type Entity = WithId & WithTimestamp;
// Discriminated union
type ApiResponse =
| { status: 'success'; data: unknown }
| { status: 'error'; message: string };
// Mapped type для объединения
type Combine<T, U> = {
[K in keyof T | keyof U]: K extends keyof T & keyof U
? T[K] | U[K]
: K extends keyof T ? T[K] : U[K];
};
// Conditional type
type Flatten<T> = T extends Array<infer U> ? U : T;

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

Начни с краткого определения union и intersection types, затем приведи практические примеры использования. Покажи понимание разницы между ними и когда какой применять. Упомяни discriminated unions как важный паттерн. Если спросят про сложные случаи, расскажи про mapped types и conditional types для динамического объединения. Приведи пример из реального проекта, где комбинирование типов решило конкретную проблему.

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

  • Понимание базовых механизмов объединения типов (union vs intersection)
  • Умение выбирать правильный подход под задачу
  • Знание продвинутых техник (discriminated unions, mapped types)
  • Понимание trade-off между гибкостью union и строгостью intersection
  • Способность объяснить на примерах из практики

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

  • Путаница между union (|) и intersection (&) - думают, что | объединяет свойства, а & - альтернативы
  • Создание intersection типов с конфликтующими полями (например, {a: string} & {a: number} приводит к never)
  • Использование union там, где нужен intersection, и наоборот
  • Игнорирование discriminated unions при работе с несколькими формами данных
  • Переусложнение типов через вложенные conditional types вместо простых union

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

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