Ответ
В статически типизированных языках (TypeScript, Rust, Haskell) union types позволяют определять переменные, которые могут хранить значения разных типов.
Основные виды:
-
Простое объединение (Untagged Union) Переменная может быть одного из нескольких типов, но у системы типов нет информации для их автоматического различения.
let id: string | number; id = "abc123"; // OK id = 123; // OK // Для использования нужна проверка типа (type guard) if (typeof id === 'string') { console.log(id.toUpperCase()); } -
Размеченное объединение (Tagged/Discriminated Union) Каждый вариант объединения имеет общее поле-дискриминатор (тег), что позволяет системе типов однозначно определить тип.
type Shape = | { kind: 'circle'; radius: number } // Тег 'circle' | { kind: 'square'; side: number } // Тег 'square' | { kind: 'rectangle'; width: number; height: number }; function getArea(shape: Shape): number { // TypeScript понимает тип по полю 'kind' switch (shape.kind) { case 'circle': return Math.PI * shape.radius ** 2; // Доступно shape.radius case 'square': return shape.side ** 2; // Доступно shape.side case 'rectangle': return shape.width * shape.height; } }
Практическая польза: Размеченные объединения исключают ошибки времени выполнения, обеспечивая полную проверку типов на этапе компиляции и устраняя необходимость в приведениях типов (type casting).
Ответ 18+ 🔞
Да ты посмотри, какие штуки придумали, блядь! Union types, ёпта! Это ж как в жизни: ну вот, допустим, у тебя в кармане может лежать либо ключ от хаты, либо зажигалка, либо, нахуй, забытая жвачка. И ты, такой, достаёшь — а там хрен пойми что. Вот это и есть простое объединение, untagged, блядь.
let id: string | number;
id = "abc123"; // О, строка, окей
id = 123; // Теперь число, тоже норм
// А вот чтобы понять, что в руках держишь — надо щупать, блядь, проверять!
if (typeof id === 'string') {
console.log(id.toUpperCase()); // Только тут уже точно знаешь — это строка, можно и покричать.
}
Но это же, сука, неудобно! Каждый раз проверять, что за хуйня у тебя в переменной? Надоест, блядь. Поэтому умные дядьки придумали размеченные объединения, tagged unions. Это уже высший пилотаж, ёбана!
Суть проста, как три копейки: каждый вариант объединения идёт с бирочкой, с тегом. Как в гардеробе — висит пальто, на крючке бирка «Петров». И ты сразу знаешь, чё это.
type Shape =
| { kind: 'circle'; radius: number } // Бирочка 'circle', внутри радиус
| { kind: 'square'; side: number } // Бирочка 'square', сторона
| { kind: 'rectangle'; width: number; height: number }; // Ну ты понял, блядь
function getArea(shape: Shape): number {
// TypeScript, он не дурак, он по бирочке 'kind' сразу соображает, что за фигура!
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2; // И даёт доступ К ТОЛЬКО К РАДИУСУ, блядь! К side уже не полезет.
case 'square':
return shape.side ** 2;
case 'rectangle':
return shape.width * shape.height;
}
}
И вся, блядь, практическая польза в чём? Да в том, что ошибки времени выполнения — это пиздец и боль. А с такими штуками компилятор тебе ещё до запуска программы ебальник набьёт, если ты где-то накосячил с типами. Никаких лишних проверок, никаких сомнительных приведений типов — чистая, ебать, математика и порядок. Красота, да и только!