Union типы
Union (|) — тип, который может быть одним из нескольких.
Базовый union
let id: string | number;
id = 'abc';
id = 42;
Union в функциях
function print(value: string | number) {
console.log(value);
}
Сужение
Чтобы использовать методы конкретного типа — нужно сузить:
function print(value: string | number) {
if (typeof value === 'string') {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
Union объектов
type Success = { status: 'success'; data: string };
type Error = { status: 'error'; message: string };
type Response = Success | Error;
Дискриминатор
Поле status — общее, но с разными литеральными значениями. По нему TypeScript понимает вариант:
function handle(res: Response) {
if (res.status === 'success') {
console.log(res.data);
} else {
console.log(res.message);
}
}
Union с null
type User = {
name: string;
email: string | null;
};
if (user.email !== null) {
console.log(user.email.toLowerCase());
}
Union с undefined
function findUser(id: number): User | undefined {
return users.find((u) => u.id === id);
}
const user = findUser(1);
if (user) {
console.log(user.name);
}
Литеральные union
type Status = 'idle' | 'loading' | 'success' | 'error';
type Size = 'sm' | 'md' | 'lg';
type Direction = 'up' | 'down' | 'left' | 'right';
Union vs Enum
// Union
type Status = 'idle' | 'loading';
// Enum
enum Status {
Idle = 'idle',
Loading = 'loading',
}
Union проще, не создаёт runtime-код, работает с JSON.
Исключающие проверки
function handle(status: Status) {
if (status === 'idle') return;
if (status === 'loading') return;
// здесь status: 'success' | 'error'
}
Сужение через in
type A = { a: string };
type B = { b: number };
function handle(value: A | B) {
if ('a' in value) {
console.log(value.a);
} else {
console.log(value.b);
}
}
Проблема широкого union
function print(value: string | number | boolean | null | undefined) {
// слишком много вариантов
}
Лучше разбить на несколько функций или использовать discriminated union.
Итоги
- Union
|— одно из нескольких - Сужение через
typeof,in, дискриминатор - Литеральные union для статусов
- Union лучше enum
- Discriminated unions — основной паттерн