Перейти до основного вмісту
Модуль 5 · Урок 1 із 29/14 у курсі~15 min
Модульні уроки (1/2)

Тип Охорона

Звуження типу є одним із найважливіших понять у TypeScript. Однак часто стандартних захисних засобів типу typeof або instanceof недостатньо для складних настроюваних об’єктів. Ось де на допомогу приходять Custom Type Guards.

Охоронці стандартного типу

Почнемо з узагальнення того, як TypeScript звужує типи за допомогою стандартних операторів JavaScript:

TS
function processInput(val: string | number) {
  if (typeof val === 'string') {
    // Here 'val' is of type string
    console.log(val.toUpperCase());
  } else {
    // Here 'val' is of type number
    console.log(val.toFixed(2));
  }
}

Охоронці спеціального типу (оператор is)

Щоб визначити спеціальний захист типу, ми створюємо функцію, яка повертає предикат типу у форматі parameterName is Type замість стандартного логічного типу повернення.

Функція має повертати логічне значення (true або false). Якщо він повертає true, TypeScript знатиме, що переданий параметр має вказаний тип.

TS
interface Cat {
  name: string;
  meow(): void;
}

interface Dog {
  name: string;
  bark(): void;
}

// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function makeNoise(pet: Cat | Dog) {
  if (isCat(pet)) {
    // Here TypeScript knows 'pet' is a Cat
    pet.meow();
  } else {
    // Here TypeScript knows 'pet' is a Dog
    pet.bark();
  }
}

Безпека та кастинг (as проти Type Guards)

Приведення типу (наприклад, val as Cat) змушує компілятор довіряти розробнику без будь-якої реальної перевірки під час виконання. Якщо об’єкт середовища виконання не відповідає очікуванням, код виконає помилку або створить винятки.

З іншого боку, спеціальні засоби захисту типів виконують надійну та динамічну перевірку часу виконання, безпечно й точно повідомляючи компілятор TypeScript про фактичний тип змінної:

TS
function processInput(input: unknown) {
  // unsafe casting: could crash if input does not have the split method
  // const str = input as string;
  // console.log(str.split(' '));

  // safe guard
  if (isString(input)) {
    console.log(input.split(' ')); // 100% Safe!
  }
}

Спробуйте самі

Вправа 1: Струнний тип Guard

вправи#ts.m5.l1.e1
Спроби: 0Завантаження…

Створіть просту функцію під назвою isString, яка діє як спеціальний захист типу, щоб перевіряти, чи є невідоме значення рядком.

Завантаження редактора…
Показати підказку

Тип повернення функції має бути val is string, і ви повинні використовувати typeof, щоб перевірити, чи дорівнює він "string".

Рішення доступне після 3 спроб

Вправа 2: Захист преміум-користувачів

вправи#ts.m5.l1.e2
Спроби: 0Завантаження…

Враховуючи типи User і PremiumUser, напишіть функцію захисту типу isPremiumUser(user: User): користувач — PremiumUser, який перевіряє, чи має користувач роль «преміум».

Завантаження редактора…
Показати підказку

Визначте підпис як функцію isPremiumUser(user: User): користувач PremiumUser і порівняйте user.role з 'premium'.

Рішення доступне після 3 спроб

Вправа 3: Перевірка власного об’єкта помилки

вправи#ts.m5.l1.e3
Спроби: 0Завантаження…

Реалізуйте функцію isCustomError(err: unknown): err — функція CustomError, яка перевіряє, чи невідоме значення є ненульовим об’єктом CustomError, що містить ключ «code».

Завантаження редактора…
Показати підказку

Спочатку перевірте, чи typeof err є 'object', а не null, потім використовуйте оператор 'in', щоб перевірити властивість 'code'.

Рішення доступне після 3 спроб

Вправа 4: Admin Type Guard

вправи#ts.m5.l1.e4
Спроби: 0Завантаження…

Маючи два інтерфейси User (з властивістю role: string) і Admin (розширює User і має властивість adminToken: string), напишіть функцію захисту типу isAdmin, яка приймає користувача типу User і повертає предикат типу user is Admin. Охоронець повинен перевірити, чи дорівнює роль користувача «адміністратору».

Завантаження редактора…
Показати підказку

Визначте підпис як функцію isAdmin(user: User): користувач адміністратор і перевірте, чи user.role === 'admin'.

Рішення доступне після 3 спроб