Skip to main content

Що означає "union narrowing"?

Що таке union type

Спочатку нагадаємо, що union type (A | B | C) - це тип, який може бути одним із кількох варіантів.

javascript
type Result = string | number;

Змінна типу Result може бути рядком або числом:

javascript
let value: Result; value = "hello"; // string value = 42; // number

Але поки TypeScript не знає, що саме зараз усередині, він не дозволить використовувати специфічні властивості.

javascript
value.toFixed(); // Помилка - може бути string

Що таке narrowing (звуження)

Narrowing - це процес, під час якого TypeScript зменшує множину можливих типів, спираючись на перевірки в коді.


Що таке union narrowing

Union narrowing - це звуження типу з об'єднання (union) до одного або кількох конкретних членів цього об'єднання, залежно від логічних умов, операторів чи перевірок.


Приклад 1. Звуження за допомогою typeof

javascript
function printValue(value: string | number) { if (typeof value === "string") { // тут value: string console.log(value.toUpperCase()); } else { // тут value: number console.log(value.toFixed(2)); } }

TypeScript "звузив" value з string | number до string в одній гілці і number - в іншій.


Приклад 2. Звуження через перевірку in

javascript
type Cat = { kind: "cat"; meow: () => void }; type Dog = { kind: "dog"; bark: () => void }; function makeSound(animal: Cat | Dog) { if ("meow" in animal) { // animal: Cat animal.meow(); } else { // animal: Dog animal.bark(); } }

Приклад 3. Звуження через літеральну властивість

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number }; function area(shape: Shape) { if (shape.kind === "circle") { // shape: { kind: "circle"; radius: number } return Math.PI * shape.radius ** 2; } else { // shape: { kind: "square"; side: number } return shape.side ** 2; } }

Це приклад discriminated union narrowing (звуження за дискримінатором - ключем kind).


Приклад 4. Звуження через instanceof

javascript
function logDate(d: Date | string) { if (d instanceof Date) { // d: Date console.log(d.toISOString()); } else { // d: string console.log(d.toUpperCase()); } }

Приклад 5. Звуження через перевірку == null

javascript
function greet(name?: string | null) { if (name == null) { // name: null | undefined console.log("No name provided"); } else { // name: string console.log("Hello, " + name); } }

Приклад 6. Звуження через власні type guards

Можна оголосити свій "фільтр типів" - функцію, яка повертає value is ...:

javascript
type Car = { wheels: 4; drive: () => void }; type Bike = { wheels: 2; pedal: () => void }; function isCar(v: Car | Bike): v is Car { return (v as Car).drive !== undefined; } function move(vehicle: Car | Bike) { if (isCar(vehicle)) { // vehicle: Car vehicle.drive(); } else { // vehicle: Bike vehicle.pedal(); } }

Що TypeScript враховує під час narrowing

TypeScript уміє автоматично аналізувати контроль потоку:

  • if, else, switch
  • typeof
  • instanceof
  • in
  • ===, !==, ==, !=
  • перевірки на null і undefined
  • власні guards (v is T)
  • return / throw / break (впливають на те, які гілки лишаються можливими)

Приклад комбінованого narrowing

javascript
function process(val: string | number | boolean | null) { if (typeof val === "string") { // val: string } else if (typeof val === "number") { // val: number } else if (val === null) { // val: null } else { // val: boolean (тип, що залишився) } }

Чому це важливо

Без narrowing TypeScript не зміг би гарантувати типову безпеку. Він би не розумів, який тип використовується в конкретній точці програми, і змушував би тебе писати as Type повсюди.

Завдяки union narrowing TypeScript вміє аналізувати логіку коду і автоматично обирати правильний підтип.


Підсумок

ТермінЗначення
Union TypeОб'єднання можливих типів (`A
NarrowingЗвуження множини можливих типів на основі умов
Union NarrowingЗвуження конкретно в об'єднанні типів
Як виконуєтьсяЧерез typeof, instanceof, in, перевірки літералів, guards
Головна метаДозволити TypeScript точно знати, який тип використовується в кожній гілці коду

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.