#9 Обробка помилок та виключень у TypeScript

Обробка помилок в TS практично не відрізняється від звичайної обробки помилок в JS, наприклад:

function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("Ділення на нуль неможливе!");
  }
  return a / b;
}

try {
  console.log(divide(10, 2)); // ✅ 5
  console.log(divide(5, 0));  // ❌ Викине помилку
} catch (error) {
  console.error("Помилка:", (error as Error).message);
}

Створення власних класів помилок

Ви можете створювати власні класи помилок, та після використовувати їх при обробці ваших помилок. Наприклад ми можемо створити клас ValidationError, після чого в валідації перевірити вік (якщо менше 18). В кетч ми перевіряємо instanceof та обробляємо помилку. 

class ValidationError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "ValidationError";
  }
}

function validateAge(age: number): void {
  if (age < 18) {
    throw new ValidationError("Вік повинен бути 18+");
  }
}

try {
  validateAge(16); // ❌ Викине ValidationError
} catch (error) {
  if (error instanceof ValidationError) {
    console.error("Помилка валідації:", error.message);
  } else {
    console.error("Невідома помилка");
  }
}

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

Ручний виклик помилки

Якщо вам потрыбно вручну викликати помилку, ви можете це зробити ось так:

function getUser(id: number) {
  if (id <= 0) {
    throw new Error("ID користувача має бути більше 0");
  }
  return { id, name: "Олексій" };
}

try {
  const user = getUser(-1); // ❌ Помилка
} catch (error) {
  console.error("Помилка отримання користувача:", (error as Error).message);
}

В цьому прикладі потрібно звернути увагу не на сам throw error, він стандартний, а на сам console.log в catch. Там ви можете побачити конструкцію as Error.  Вона необхідна, тому що по дефолту TS не знає що таке error, і вам потрібно вказати йому, що error має тип помилки error (змінна) as Error (тип).

Функції які завжди викидають помилки

Для таких функцій потрібно використовувати тип never. Цей тип говорить про те, що функція або ніколи не закінчується, або завжди викидає помилку.

function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) {
    console.log("Цей цикл ніколи не закінчиться");
  }
}

Приклад обробки помилок в fetch

async function fetchData(url: string) {
  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error(`Помилка HTTP: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error("Помилка запиту:", (error as Error).message);
    return null;
  }
}

fetchData("https://jsonplaceholder.typicode.com/posts/1")
  .then(data => console.log("Отримані дані:", data));