Объединения и пересечения типов
Объединения и пересечения — это мощные инструменты TypeScript для комбинирования типов. Они позволяют точно описывать данные, которые могут принимать несколько форм или объединять свойства из разных источников.
Объединение типов (|)
Объединение (union) означает, что значение может соответствовать одному из нескольких типов. Обозначается вертикальной чертой |.
type ID = string | number;
function printId(id: ID): void {
console.log(`ID: ${id}`);
}
printId("user_123"); // строка — допустимо
printId(42); // число — допустимо
Литеральные объединения
Часто объединения используются с литералами для ограничения допустимых значений:
type Status = "active" | "inactive" | "pending";
function updateStatus(status: Status): void {
// ...
}
updateStatus("active"); // OK
updateStatus("deleted"); // Ошибка: не входит в union
Такие типы делают код самодокументируемым и предотвращают ошибки при передаче недопустимых значений.
Пересечение типов (&)
Пересечение (intersection) создаёт тип, который объединяет все свойства из нескольких типов. Значение должно соответствовать всем указанным типам одновременно.
interface User {
name: string;
email: string;
}
interface Admin {
role: string;
permissions: string[];
}
type AdminUser = User & Admin;
const admin: AdminUser = {
name: "Алексей",
email: "alex@example.com",
role: "editor",
permissions: ["read", "write"]
};
Пересечение особенно полезно при композиции пропсов в React-компонентах или при расширении базовых типов без наследования.
Сравнение с наследованием интерфейсов
Интерфейсы можно расширять через extends, но это работает только с другими интерфейсами. Пересечение работает с любыми типами — interface, type, примитивами и даже объединениями.
type BaseProps = { className?: string };
type ButtonVariant = { variant: "primary" | "secondary" };
type ButtonProps = BaseProps & ButtonVariant;
Это гибче, чем interface, особенно когда исходные типы определены как type.
Ограничения и проверка типов
При работе с объединениями TypeScript требует убедиться, что операция допустима для всех возможных вариантов. Часто используется проверка типа через typeof или сравнение со строковыми литералами.
function processValue(value: string | number): void {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
}
Без такой проверки TypeScript не позволит вызывать методы, специфичные только для одного из типов в объединении.