Skip to main content

Що таке type narrowing?

Що таке Type Narrowing (звуження типу)

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

Простіше кажучи: Якщо змінна може мати кілька типів (наприклад, string | number), TypeScript "звужує" цей набір, коли ти робиш перевірки на кшталт typeof, in, instanceof тощо.


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

javascript
function printId(id: string | number) { if (typeof id === "string") { // Тут id: string console.log("Рядок:", id.toUpperCase()); } else { // Тут id: number console.log("Число:", id.toFixed(2)); } }

TypeScript сам розуміє:

  • всередині if (typeof id === "string") -> id став string
  • всередині else -> id став number

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

javascript
class User { constructor(public name: string) {} } class Admin { constructor(public name: string, public permissions: string[]) {} } function printPerson(person: User | Admin) { if (person instanceof Admin) { // Тут person: Admin console.log("Права:", person.permissions); } else { // Тут person: User console.log("Звичайний користувач:", person.name); } }

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

javascript
type User = { name: string }; type Admin = { name: string; permissions: string[] }; function printInfo(person: User | Admin) { if ("permissions" in person) { // person: Admin console.log("Права:", person.permissions); } else { // person: User console.log("Ім'я:", person.name); } }

in перевіряє наявність властивості, і TypeScript використовує це для логічного звуження типів.


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

TypeScript теж вміє "розуміти" тип після таких перевірок:

javascript
function process(value: string | null) { if (value !== null) { // value: string console.log(value.toUpperCase()); } }

Приклад 5. Звуження через "truthy/falsy" значення

TypeScript знає, що null, undefined, 0, "", false - "falsy" значення.

javascript
function printName(name?: string) { if (name) { // name: string console.log("Привіт,", name.toUpperCase()); } else { // name: undefined console.log("Ім'я не вказано"); } }

Приклад 6. Користувацькі перевірки типів (Type Guards)

Можна створити свою функцію, яка допомагає TypeScript звужувати тип:

javascript
type User = { name: string }; type Admin = { name: string; permissions: string[] }; function isAdmin(person: User | Admin): person is Admin { return "permissions" in person; } function handle(person: User | Admin) { if (isAdmin(person)) { // Тут TS знає, що person: Admin console.log("Права:", person.permissions); } else { // Тут person: User console.log("Користувач:", person.name); } }

person is Admin - це user-defined type guard, який повідомляє TS, який саме тип повернеться з перевірки.


Приклад 7. Звуження всередині switch

javascript
type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number } | { kind: "triangle"; base: number; height: number }; function getArea(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; case "triangle": return (shape.base * shape.height) / 2; } }

Тут TypeScript використовує дискриміноване об'єднання і автоматично звужує тип у кожній гілці case.


Де використовується type narrowing

СценарійПриклад перевірки
Примітивиtypeof value === "string"
Класиinstanceof SomeClass
Об'єкти"prop" in obj
Порівнянняif (x !== null)
Булеві перевіркиif (value)
Власні функції-охоронціvalue is Type
switch-дискримінаціяcase "circle": …

Навіщо це потрібно

Type narrowing дозволяє:

  • працювати без помилок при union-типах;
  • отримувати автодоповнення і підказки в IDE;
  • писати безпечний і читабельний код без зайвих приведень типів (as).

Коротко:

Type narrowing - це коли TypeScript "розуміє", який саме тип у змінної в певний момент, і автоматично звужує загальний тип до конкретного в різних гілках коду.

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

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

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