Skip to main content

Що таке type guard function?

Що таке Type Guard Function

Type guard function - це спеціальна функція, яка повертає логічне значення і повідомляє TypeScript, що якщо вона повернула true, значить її аргумент має конкретний тип.

Синтаксис:

javascript
function isSomething(value: unknown): value is SomeType { // логіка перевірки }

Ключова частина - це тип, що повертається: value is SomeType -> type predicate (твердження про тип).


Приклад 1. Базовий кастомний type guard

javascript
function isString(value: unknown): value is string { return typeof value === "string"; } function print(value: unknown) { if (isString(value)) { // тут value: string console.log(value.toUpperCase()); } else { // value не string console.log("Not a string"); } }

Завдяки value is string, TypeScript розуміє, що всередині if (isString(value)) тип змінної звузився до string.


Навіщо потрібні Type Guard Functions

  1. Щоб розширити систему типів TypeScript - навчити її розуміти твої перевірки.
  2. Щоб уникнути примусових приведень (as).
  3. Щоб безпечно працювати з unknown, any чи union-типами.
  4. Щоб звужувати типи всередині логічних умов, фільтрів і функцій вищого порядку.

Приклад 2. Перевірка масиву

javascript
function isArray(value: unknown): value is any[] { return Array.isArray(value); } function process(value: unknown) { if (isArray(value)) { // value: any[] console.log(value.length); } else { console.log("Not an array"); } }

Як це працює під капотом

Звичайна функція повертає boolean:

javascript
function check(value: unknown): boolean

TypeScript не може з цього вивести тип. А функція з type predicate (value is Type) каже компілятору:

"Якщо я повернув true, вважай, що змінна тепер має тип Type".


Приклад 3. З union типом

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

Це типовий приклад type guard + narrowing: функція isDog звужує union-тип Dog | Cat до конкретного підтипу.


Де часто використовується

СценарійПриклад
Перевірка типу аргументуisString(x)
Перевірка на null/undefinedisNonNull(x)
Перевірка дискримінатораisError(response)
Перевірка instanceofisDate(obj)
Фільтрація масивуarr.filter(isString)

Приклад 4. Фільтрація масиву з Type Guard

javascript
function isString(value: unknown): value is string { return typeof value === "string"; } const mixed = [1, "a", 2, "b", true]; const strings = mixed.filter(isString); // strings: string[]

TypeScript знає, що після фільтра залишилися лише string.


Приклад 5. Перевірка складних структур

javascript
type User = { id: number; name: string }; function isUser(obj: any): obj is User { return ( typeof obj === "object" && obj !== null && typeof obj.id === "number" && typeof obj.name === "string" ); } const data: unknown = JSON.parse('{"id":1,"name":"Tom"}'); if (isUser(data)) { // data: User console.log(data.name.toUpperCase()); }

Без type guard'а довелося б писати:

javascript
const user = data as User; // небезпечно, може впасти в рантаймі

Приклад 6. Перевірка на існування ключа

javascript
function hasProperty<T extends object, K extends PropertyKey>( obj: T, key: K ): obj is T & Record<K, unknown> { return key in obj; } const person = { name: "Alex" }; if (hasProperty(person, "name")) { // person: { name: string } & Record<"name", unknown> console.log(person.name); }

Приклад 7. Композиція декількох type guards

javascript
function isDefined<T>(value: T | undefined | null): value is T { return value != null; } function isPositive(n: number): boolean { return n > 0; } const arr = [1, null, 2, undefined, -5, 3]; const positive = arr.filter(isDefined).filter(isPositive); // positive: number[]

Після isDefined TypeScript знає, що в масиві більше немає null чи undefined.


Відмінність Type Guard Function від звичайної функції

Звичайна функціяType Guard Function
Повертає booleanПовертає value is Type
Не змінює тип змінноїЗвужує тип змінної
Не впливає на компіляторЗмінює сприйняття типу TS
Використовується як логічна перевіркаВикористовується як доказ типу

Приклад: як TS "думає"

javascript
if (isUser(obj)) { // TypeScript "повірив" перевірці isUser // obj: User } else { // obj: unknown }

TypeScript не виконує функцію, він просто довіряє анотації value is Type - це обіцянка розробника, що логіка функції справді правильна.


Важливі зауваження

  1. TypeScript не перевіряє коректність перевірки всередині - це відповідальність розробника.
javascript
function isNumber(x: any): x is number { return typeof x === "string"; // TS повірить, навіть якщо це помилка }
  1. Type guards працюють лише з параметром функції, а не з довільними змінними.
  2. Можна використовувати generics, щоб робити універсальні guards.

Підсумок

ТермінВизначення
Type Guard FunctionФункція, яка повертає value is Type і повідомляє TS, що значення має вказаний тип
ПризначенняЗвуження типів і безпечна робота з unknown, any та union-типами
Головна особливістьВпливає на аналіз типів, а не лише на логіку виконання
Типовий синтаксисfunction isUser(obj: any): obj is User { ... }
Головна перевагаБезпека, автодоповнення і відсутність as

Просто запам'ятай:

Type Guard Function - це "охоронець", який каже TypeScript: "я перевірив, можеш довіряти - це саме цей тип".

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

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

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