Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке type guard function?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Type guard function** - це спеціальна функція, яка повертає логічне значення і повідомляє TypeScript, що якщо вона повернула `true`, значить її аргумент має конкретний тип - через анотацію `value is SomeType` (type predicate). **Ключове:** TypeScript не виконує тіло функції і не перевіряє коректність логіки всередині - він просто довіряє анотації `value is Type` як обіцянці розробника.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке 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/undefined | `isNonNull(x)` | | Перевірка дискримінатора | `isError(response)` | | Перевірка instanceof | `isDate(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 повірить, навіть якщо це помилка } ``` 2. **Type guards працюють лише з параметром функції**, а не з довільними змінними. 3. **Можна використовувати generics**, щоб робити універсальні guards. --- ## Підсумок | Термін | Визначення | |---|---| | **Type Guard Function** | Функція, яка повертає `value is Type` і повідомляє TS, що значення має вказаний тип | | **Призначення** | Звуження типів і безпечна робота з `unknown`, `any` та union-типами | | **Головна особливість** | Впливає на аналіз типів, а не лише на логіку виконання | | **Типовий синтаксис** | `function isUser(obj: any): obj is User { ... }` | | **Головна перевага** | Безпека, автодоповнення і відсутність `as` | --- **Просто запам'ятай:** > Type Guard Function - це "охоронець", > який каже TypeScript: "я перевірив, можеш довіряти - це саме цей тип".Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.