Пересечение типов в TypeScript

Пересечение типов в TypeScript

Даниил Шило

Сегодня обсудим пересечение в TypeScript. Тема достаточно сложная для понимания, ибо пересечение в TypeScript сильно отличается от классического пересечения в дискретной математике.

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

Из дискретной математики для понимания операторов | и & нам понадобятся только два определения:

  1. Пересечением двух множеств называется множество, которому одновременно принадлежат элементы из первого и из второго множества.
  2. Объединением двух множеств называется множество, которому принадлежат только те элементы, которые есть или в первом, или во втором множестве.

В общем-то говоря, пересечением в TypeScript называется объект со всеми свойствами и методами, которые одновременно принадлежат и первому и второму типу, а объединением называется объект со всем свойствами или из первого, или второго типа😳
Говоря о пересечении, очень удобно представлять как два множества "сплющились" и создали одно большое множество с общими свойствами (что конечно, в дискретной математике называется не пересечением, а эквивалентными множествами, где два множества находятся в отношении подмножества друг-друга).

Диаграммы Венна-Эйлера для пересечений и объединений в TypeScript

Простое правило👀: Если тяжеловато справится с дискретной математикой то, вот простое правило:

  • Пересечение - когда все свойства объекта находятся и в первом, и во втором типе
  • Объдинение - когда все свойства объекта находятся хотя бы в одном из типов

Именно поэтому, кстати, при объединении number | string, мы можем использовать только общие методы. Мы не можем использовать специфические методы, потому что не знаем в каком из множеств находимся😊

Вопрос: Почему все так запутано?! Почему при объединении мы можем использовать свойства, которые есть только в двух типах, разве это не пересечение?

Ответ: Черт бы побрал, но тут есть доля правды, единственное - когда разрабатывали язык, то ссылались не на свойства и методы типов, а на сами типы.

Пример: объединение строки и числа — число или строка. Вот и вся магия. TypeScript просто защищает вас, чтобы вы не использовали случаем метод для числа, когда работаете со строкой, вот и не дает использовать метод из прототипа числа.

Ещё пример: пересечение строки и числа?! Его нет! Мы только что заставили TypeScript найти значение, которое обязательно пересекается и в множестве чисел, и в множестве строк. TypeScript — не JavaScript, он не будет возвращать нам null (пустое множество), он просто вернет never (тип в который вообще ничего нельзя положить):

Пересечение числа и строки

Когда мы пересекаем объекты, а не примитивы, то мы как бы даем понять TypeScript'у, что мы хотим специально сделать пересечение всех параметров, он скрещивает их в одно большое множество и делает все параметры из первого и второго объекта обязательными:

Пересечение двух объектов


Report Page