ПрограммированиеBackend TypeScript разработчик

Расскажите о механизме 'типов пересечений' (intersection types) в TypeScript. Как их правильно использовать и с какими подводными камнями можно столкнуться?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Типы пересечений (&, intersection types) позволяют комбинировать несколько типов в один, обладающий всеми свойствами объединённых типов.

Пример:

type Person = { name: string }; type Worker = { job: string }; type WorkingPerson = Person & Worker; // { name: string; job: string } const wp: WorkingPerson = { name: "Leo", job: "Dev" };

Это удобно при композиции расширяемых контрактов и построении сложных типов из примитивов.

Однако, если пересекаются несовместимые типы (например, type A = { foo: string } и type B = { foo: number }), получается тип, который невозможно инициализировать.

Пример некорректного пересечения:

type A = { foo: string }; type B = { foo: number }; type C = A & B; // C = { foo: never }

Вопрос с подвохом

Что будет, если пересечь два типа, в которых есть одинаковое поле с несовместимыми типами данных?

Ответ: Получится поле с типом never, так как значение одновременно не может быть и строкой, и числом. Такой тип нельзя валидно реализовать.

type T1 = { id: string }; type T2 = { id: number }; type T3 = T1 & T2; // { id: never }

Примеры реальных ошибок из-за незнания тонкостей темы


История

В проекте пересекали типы от разных библиотек, не замечая, что есть одинаковые поля с разными типами. В результате получался непредвиденный "невозможный" (never) тип, который приводил к невозможности создать валидный объект для передачи в API.


История

Разработчику нужно было "склеить" типы DTO и доменной сущности. В пересечении оказалось два несовместимых свойства, и попытка использовать получившийся тип вызывала неоднозначные ошибки компиляции. Разработчик потратил время на дебаг, прежде чем понял причину.


История

В одном из микросервисов был объявлен пересечённый тип для описания тела запроса. Из-за изменения API одно из свойств получило иной тип, и новые изменения сразу не привели к компиляционной ошибке — проблемы появились только в рантайме после деплоя.