Модульні уроки (2/2)
Союзи і звуження
У реальному світі змінні та відповіді API не завжди мають єдиний фіксований тип. TypeScript пропонує Union Types для обробки змінності та Type Narrowing для безпечної роботи з ними під час виконання.
Типи спілок
Тип об’єднання дозволяє змінній приймати значення різних типів. Це виражається символом вертикальної риски (|):
let result: number | string;
result = 42; // Valid
result = 'Error 404'; // ValidОднак під час роботи з типом об’єднання ми не можемо напряму викликати методи, які належать лише до одного з типів (наприклад, ми не можемо викликати .toUpperCase(), якщо змінна також може бути number). Спочатку треба «звузити» тип.
Тип Звуження
Звуження типу — це процес, у якому TypeScript аналізує структури потоку керування (наприклад, if або switch), щоб визначити більш конкретний тип для змінної під час виконання.
Існує кілька способів виконання звуження:
1. Оператор typeof
Ідеально підходить для розрізнення примітивних типів:
function printLength(value: string | number) {
if (typeof value === 'string') {
// TypeScript knows 'value' is a string here
console.log(value.length);
} else {
// TypeScript knows 'value' is a number here
console.log(value.toFixed(2));
}
}2. Оператор in
Використовується для перевірки наявності певної властивості об’єкта:
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function move(animal: Fish | Bird) {
if ('swim' in animal) {
animal.swim(); // Narrowing to Fish
} else {
animal.fly(); // Narrowing to Bird
}
}Дискриміновані профспілки
Шаблон Дискриміновані об’єднання складається зі створення об’єктів, які мають спільну властивість з унікальним літеральним значенням (званим дискримінатором). TypeScript розпізнає цей дискримінатор і автоматично звужує тип у межах умовних блоків.
interface SuccessResponse {
status: 'success'; // Literal discriminator
data: string;
}
interface ErrorResponse {
status: 'error'; // Literal discriminator
errorMessage: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
console.log('Data received:', response.data);
} else {
console.error('An error occurred:', response.errorMessage);
}
}Спробуйте самі
Вправа 1: Типи союзів
Оголошіть змінну з іменем id, яка може бути або числом, або рядком. Спочатку ініціалізуйте його числом 101, а потім призначте значення рядка "USER-101".
Показати підказку
Використовуйте | оператор для об’єднання числа та рядка в оголошенні змінної let.
Рішення доступне після 3 спроб
Вправа 2: Звуження базового типу
Створіть функцію під назвою formatInput, яка приймає вхідний параметр типу string або number. Якщо введення є рядком, повертає введення, перетворене на верхній регістр. Якщо це число, поверніть вхідні дані, помножені на 2. Явно вкажіть типи.
Показати підказку
Використовуйте typeof input === 'string' всередині блоку if, щоб розгалужити поведінку.
Рішення доступне після 3 спроб
Вправа 3: Звуження за допомогою "в"
Маючи два інтерфейси Car (з методом drive) і Boat (з методом sail), напишіть функцію з назвою moveVehicle, яка приймає параметр vehicle типу Car або Boat. Якщо транспортний засіб має властивість drive, виконайте метод drive(). В іншому випадку виконайте метод sail().
Показати підказку
Використовуйте оператор in у формі 'drive' in vehicle, щоб звузити інтерфейс.
Рішення доступне після 3 спроб
Вправа 4: Дискримінована форма об’єднання
Визначте тип Shape, який є об’єднанням двох типів: Circle та Square. Circle має властивість типу 'circle' (літеральне значення) і радіус (число). Square має властивість типу 'квадрат' (літеральне значення) і сторону (число). Потім напишіть функцію getArea, яка приймає форму типу Shape і повертає площу як число (для кола Math.PI * радіус * радіус, для квадрата * сторона).
Показати підказку
Використовуйте shape.kind === 'circle' всередині getArea, щоб розрізнити тип і обчислити правильну площу.
Рішення доступне після 3 спроб