История вопроса:
Union types появились в TypeScript для описания переменных и параметров, которые могут принимать значения разных типов. Эта возможность значительно расширила гибкость типизации по сравнению с классическими языками.
Проблема:
В JavaScript функции и переменные часто бывают многоформатными (например, принимают число или строку), что усложняет безопасную типизацию. Без union types приходилось использовать any или дублировать код. Это увеличивало количество ошибок на продакшене и затрудняло работу в больших командах.
Решение:
Union types позволяют объявлять переменную, которая может быть одного из нескольких типов, гарантированно поддерживая корректные операции после проверки. Также реализована поддержка сужения типов (type narrowing), что помогает компилятору "понять", с чем он имеет дело.
Пример кода:
function formatId(id: number | string): string { if (typeof id === 'string') { return id.toUpperCase(); } return id.toString(); }
Ключевые особенности:
Можно ли записать union из объектов с разными свойствами и обращаться к любому свойству без проверки?
Нет. Union types позволяют обращаться только к тем свойствам и методам, которые присутствуют во всех типах. Для доступа к частным свойствам требуется сужение типа.
Пример кода:
type Fish = { swim: () => void; }; type Bird = { fly: () => void; }; function move(animal: Fish | Bird) { // animal.swim(); // Ошибка без сужения if ('swim' in animal) { animal.swim(); // ОК } }
Почему не все методы доступны для union типа строка | число?
TypeScript в union разрешает только то, что есть во всех включенных типах. Для индивидуальных методов нужно сначала проверить реальный тип.
Что произойдет, если не проверять тип в union, а попытаться вызвать специфичный метод?
В таком случае возникнет ошибка компиляции, так как не гарантируется наличие метода. Работает только после проверки конкретного типа.
Дали переменной тип string | number и без проверки сделали toUpperCase(). В результате приложение падает на числовых данных.
Плюсы:
Минусы:
Проверяем тип перед работой с методом:
if (typeof value === 'string') { return value.toUpperCase(); } else { return value.toString(); }
Плюсы:
Минусы: