Типы пересечения (Intersection Types) в TypeScript позволяют создавать составные типы, которые сочетают в себе свойства и методы всех исходных типов. Это мощный инструмент для построения гибких и расширяемых структур данных без избыточного наследования классов. Конструкция реализуется с помощью оператора & между типами.
TypeScript с первых версий поддерживает объединённые типы (|) для выражения “или”, но часто возникает задача описать объект с множеством свойств из разных независимых интерфейсов или типов. Тогда используется пересечение (&) — объект должен удовлетворять всем интерфейсам по всем свойствам.
Одной из главных сложностей является конфликт одинаковых имён свойств в пересекаемых типах, различие в их типизации, а также корректность итогового комбинированного типа, если объединяются классы с приватными или защищёнными полями. Также часто путают пересечение типов с объединением (union types), что приводит к неочевидным ошибкам компиляции или работе с объектом.
Пересечение типов агрегирует все свойства из объединяемых типов, и для каждого свойства требуется соответствие обоим типам, если имя совпадает. Используется как для интерфейсов, так и для type-алиасов.
interface A { foo: string; } interface B { bar: number; } type AB = A & B; const item: AB = { foo: "hello", bar: 123 }; // Корректно
Если пересекаются свойства с одинаковым именем, тип должен совпадать, иначе возникает ошибка:
interface X { val: string; } interface Y { val: number; } // type Z = X & Y; // Ошибка: несовместимость val
Ключевые особенности:
& объединяет все свойства обоих типов (интерфейсы и type-алиасы).Что произойдёт, если типы пересекаются, а некоторые свойства имеют несовместимые типы? (Например, одно свойство string, другое number)
Будет ошибка компиляции, т.к. свойство не может быть и string и number одновременно.
Можно ли пересекать классы с приватными или защищёнными свойствами?
Можно, но если такие поля есть с одинаковыми именами и разными типами доступа, результат будет невалидным, и TypeScript выдаст ошибку.
Чем intersection type отличается от union type (|)?
Пересечение (A & B) требует, чтобы объект был одновременно обоих типов, а объединение (A | B) — чтобы был хотя бы одним из них. Например:
type U = A | B; // Можно foo или bar или оба type I = A & B; // Обязательно оба свойства
Разработчик создаёт тип через пересечение нескольких несогласованных интерфейсов; свойства конфликтуют, возникают трудные для отладки ошибки типизации.
Плюсы: Возможность быстро объединить возможности нескольких типов
Минусы: Код не компилируется либо содержит неявные баги, отладка сложна
Разделение функций на независимые интерфейсы и аккуратное объединение их через intersection type для формирования конечных composite-объектов.
Плюсы: Масштабируемость, простота тестирования и расширения, строгий контракт
Минусы: Дополнительная работа по проектированию интерфейсов и их согласованию