Skip to main content

Як розширити Error власними властивостями?

1. Основна ідея

Ти створюєш власний клас, який успадковується від Error, і додаєш до нього потрібні властивості - наприклад: code, status, details, cause, context тощо.

2. Приклад: базова кастомна помилка

javascript
class AppError extends Error { constructor(message, code) { super(message); // передаємо повідомлення батьку (Error) this.name = "AppError"; // задаємо ім'я помилки this.code = code; // додаємо власну властивість } } try { throw new AppError("Щось пішло не так", "SERVER_ERROR"); } catch (e) { console.log(e.name); // AppError console.log(e.message); // Щось пішло не так console.log(e.code); // SERVER_ERROR console.log(e.stack); // Стек викликів }

Тепер у твоєї помилки є і стандартні властивості (message, stack), і кастомні (code).

3. Приклад: додавання HTTP-коду і контексту

Це зручно для API, особливо в NestJS / Express:

javascript
class HttpError extends Error { constructor(message, status = 500, details = {}) { super(message); this.name = this.constructor.name; this.status = status; this.details = details; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } } throw new HttpError("Користувача не знайдено", 404, { userId: 123 });

При обробці помилки:

javascript
try { throw new HttpError("Користувача не знайдено", 404, { userId: 123 }); } catch (err) { console.log(err.name); // HttpError console.log(err.status); // 404 console.log(err.details); // { userId: 123 } }

4. Приклад: ієрархія кастомних помилок

Можна побудувати ціле "дерево" помилок:

javascript
class AppError extends Error { constructor(message, code) { super(message); this.name = this.constructor.name; this.code = code; Error.captureStackTrace?.(this, this.constructor); } } class ValidationError extends AppError { constructor(message, field) { super(message, "VALIDATION_ERROR"); this.field = field; } } class AuthError extends AppError { constructor(message = "Unauthorized") { super(message, "AUTH_ERROR"); this.status = 401; } }

Використання:

javascript
try { throw new ValidationError("Невірний email", "email"); } catch (err) { if (err instanceof ValidationError) { console.log("Помилка в полі:", err.field); } console.log(err.code); // VALIDATION_ERROR }

5. Приклад з cause (ES2022+)

Сучасний стандарт ECMAScript підтримує властивість cause, щоб зберігати вихідну помилку, через яку виникла поточна.

javascript
try { JSON.parse("invalid JSON"); } catch (parseErr) { throw new AppError("Помилка під час розбору JSON", "PARSE_ERROR", { cause: parseErr }); }

Щоб підтримувати cause, потрібно додати його в конструктор:

javascript
class AppError extends Error { constructor(message, code, options = {}) { super(message, options); this.name = this.constructor.name; this.code = code; this.cause = options.cause; } }

6. Приклад використання в продакшені (Express / NestJS)

javascript
app.use((err, req, res, next) => { if (err instanceof AppError) { res.status(err.status || 500).json({ error: err.name, message: err.message, code: err.code, details: err.details, }); } else { res.status(500).json({ error: "InternalError", message: "Невідома помилка" }); } });

7. Навіщо розширювати Error

ПричинаПриклад
Чіткі й зрозумілі повідомлення"Email обов'язковий" замість "Unexpected token"
Структура і типізаціяValidationError, AuthError, HttpError
Зручність логуванняМожна включати code, status, details
Зберігання вихідної причиничерез cause
Зручність відлагодженняРізні типи помилок легко розрізняти в catch

Підсумок

Щоб розширити Error власними властивостями:

javascript
class MyError extends Error { constructor(message, customProp) { super(message); this.name = "MyError"; this.customProp = customProp; Error.captureStackTrace?.(this, this.constructor); } }

І використовувати:

javascript
throw new MyError("Помилка БД", { query: "SELECT * FROM users" });

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

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

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