Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як повертати помилки через тип Result замість винятків і коли це виправдано?

Проблема винятків у TypeScript: сигнатура функції не каже, які помилки вона може кинути. function parse(s: string): Config може кинути що завгодно, а в catch (error) змінна має тип unknown. Компілятор не змусить обробити помилку.

Тип Result робить помилку частиною повернутого значення:

type Result<T, E = Error> =
  | { ok: true; value: T }
  | { ok: false; error: E };

type AgeError = 'not-a-number' | 'negative' | 'too-large';

function parseAge(input: string): Result<number, AgeError> {
  const n = Number(input);
  if (Number.isNaN(n)) return { ok: false, error: 'not-a-number' };
  if (n < 0) return { ok: false, error: 'negative' };
  if (n > 150) return { ok: false, error: 'too-large' };
  return { ok: true, value: n };
}
const result = parseAge(form.age);

if (!result.ok) {
  showError(messages[result.error]);   // error: AgeError - відомо, які бувають
  return;
}
saveAge(result.value);                 // value: number - лише після перевірки

Що це дає:

  • помилки видно в сигнатурі - і їх неможливо «забути»: до value не дістатися без перевірки ok;
  • точні типи помилок - перелік очікуваних випадків, а не unknown;
  • вичерпна обробка: switch (result.error) з перевіркою never гарантує, що кожен варіант оброблено;
  • легко тестувати: функція повертає дані, а не кидає.

Коли Result виправданий:

  • очікувані бізнес-помилки: валідація, «товару немає на складі», «недостатньо коштів», відповіді API з відомими кодами;
  • місця, де помилку треба обробити поруч з викликом.

Коли краще винятки:

  • неочікувані збої (баги, недоступна мережа, порушені інваріанти) - їх обробляють на межі застосунку, а не в кожному виклику;
  • код, що працює з фреймворками, які очікують винятків (межі помилок React, обробники помилок у Laravel-стилі).

Пастки:

  • ланцюжки Result-ів многослівні (if (!r.ok) return r; на кожному кроці). Бібліотеки (neverthrow, Effect) дають map, andThen - але додають новий стиль коду, який команда має прийняти;
  • змішування стилів: функція, що повертає Result, але всередині може кинути виняток, - найгірший варіант. Межа має бути чіткою: на якому рівні винятки перетворюються на Result.

Докладніше в документації: Дискриміновані об'єднання

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання