Пошук уроків, статей та іншого контенту
Тип, що позначає «одне з кількох значень» — і патерн, що робить розрізнення варіантів безпечним.
Оператор | створює union-тип — значення, що може бути одним із перелічених варіантів. Це вже траплялось у попередніх уроках (Status як union літеральних рядків) — union працює так само й для звичайних типів, не лише літералів:
function formatId(id: string | number): string {
return `ID-${id}`;
}
formatId("abc123"); // ок, string входить у union
formatId(42); // ок, number теж входить у union
// formatId(true); // помилка компіляції — boolean не входить у дозволений unionЯкщо union об'єднує кілька форм об'єкта, компілятор дозволяє звертатись лише до полів, спільних для усіх варіантів union, — доступ до поля, що існує лише в одному з них, без попередньої перевірки типу є помилкою компіляції:
type Circle = { radius: number };
type Square = { side: number };
function getArea(shape: Circle | Square): number {
// return shape.radius * shape.radius * Math.PI; // помилка: radius не гарантовано існує в Square
}Патерн discriminated union додає спільне поле (типово kind чи type) з унікальним літеральним значенням для кожного варіанта — компілятор потім використовує це поле, щоб точно звузити, з яким саме варіантом union він працює всередині конкретної гілки коду:
type Circle = { kind: "circle"; radius: number };
type Square = { kind: "square"; side: number };
type Shape = Circle | Square;
function getArea(shape: Shape): number {
if (shape.kind === "circle") {
return shape.radius * shape.radius * Math.PI; // тут TypeScript ЗНАЄ: shape — саме Circle
}
return shape.side * shape.side; // тут — точно Square, інших варіантів не лишилось
}Для union із кількома варіантами switch за полем-дискримінантом читається природніше за ланцюжок if/else, і дозволяє компілятору перевірити вичерпність — чи всі варіанти справді оброблені (детально в уроці про type narrowing далі в цьому модулі):
function describe(shape: Shape): string {
switch (shape.kind) {
case "circle":
return `Коло радіусом ${shape.radius}`;
case "square":
return `Квадрат зі стороною ${shape.side}`;
}
}Union форм об'єктів без спільного поля-дискримінанта — компілятор не може автоматично звузити тип за жодною умовою, і доступ до специфічних полів вимагає незручних ручних перевірок наявності поля.
Використання однакового імені поля-дискримінанта з нелітеральним типом (kind: string замість kind: "circle") — компілятор більше не може звужувати за конкретним значенням, лише за загальним типом string.
Забуття одного з варіантів у switch/if-ланцюжку без перевірки вичерпності — код компілюється, але мовчки не обробляє один із можливих варіантів даних.
Union-тип (|) описує значення одного з кількох варіантів; доступ дозволений лише до полів, спільних для всіх варіантів, доки компілятор не звузить конкретний варіант через перевірку умови. Discriminated union — практичний патерн зі спільним літеральним полем-дискримінантом (kind), що дозволяє компілятору точно й безпечно звужувати тип усередині if/switch, замість незручних ручних перевірок наявності полів.