Этот вопрос проверяет знание создания специализированных типов ошибок в TypeScript и понимание наследования встроенного класса Error.
Да, можно создать собственный тип ошибки. Для этого нужно создать класс, который наследуется от встроенного класса Error, и добавить необходимые свойства и методы. В конструкторе обязательно нужно вызвать super() и установить Object.setPrototypeOf(this, CustomError.prototype) для правильной работы instanceof.
Собственные типы ошибок позволяют создавать специализированные исключения с дополнительной информацией.
typescript
class CustomError extends Error {
constructor(message: string) {
super(message);
// Важно для правильной работы instanceof
Object.setPrototypeOf(this, CustomError.prototype);
// Сохраняем стек вызовов
if (Error.captureStackTrace) {
Error.captureStackTrace(this, CustomError);
}
this.name = "CustomError";
}
}typescript
class ValidationError extends Error {
public readonly field: string;
public readonly value: any;
constructor(field: string, value: any, message?: string) {
super(message || `Ошибка валидации поля ${field}`);
this.name = "ValidationError";
this.field = field;
this.value = value;
Object.setPrototypeOf(this, ValidationError.prototype);
}
}
class NetworkError extends Error {
public readonly statusCode: number;
public readonly url: string;
constructor(statusCode: number, url: string, message?: string) {
super(message || `Сетевая ошибка ${statusCode} для ${url}`);
this.name = "NetworkError";
this.statusCode = statusCode;
this.url = url;
Object.setPrototypeOf(this, NetworkError.prototype);
}
}typescript
function validateUser(user: any): void {
if (!user.name) {
throw new ValidationError("name", user.name, "Имя обязательно");
}
if (user.age < 0) {
throw new ValidationError("age", user.age, "Возраст не может быть отрицательным");
}
}
function fetchUser(id: number): Promise<User> {
return fetch(`/api/users/${id}`)
.then(response => {
if (!response.ok) {
throw new NetworkError(response.status, `/api/users/${id}`);
}
return response.json();
});
}typescript
try {
validateUser({ age: -1 });
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Ошибка в поле ${error.field}:`, error.message);
// Ошибка в поле age: Возраст не может быть отрицательным
} else {
console.error("Неизвестная ошибка:", error);
}
}Можно создавать сложные иерархии ошибок:
typescript
abstract class AppError extends Error {
public abstract readonly code: string;
constructor(message: string) {
super(message);
this.name = this.constructor.name;
Object.setPrototypeOf(this, new.target.prototype);
}
}
class DatabaseError extends AppError {
public readonly code = "DB_ERROR";
public readonly query: string;
constructor(query: string, message: string) {
super(message);
this.query = query;
}
}
class UniqueConstraintError extends DatabaseError {
public readonly code = "UNIQUE_CONSTRAINT";
public readonly constraint: string;
constructor(constraint: string, query: string) {
super(query, `Нарушено ограничение уникальности: ${constraint}`);
this.constraint = constraint;
}
}typescript
// Без этого instanceof не будет работать правильно
Object.setPrototypeOf(this, CustomError.prototype);typescript
this.name = this.constructor.name; // Автоматически устанавливает имяtypescript
class BusinessError extends Error {
public readonly code: string;
constructor(code: string, message: string) {
super(message);
this.code = code;
this.name = "BusinessError";
Object.setPrototypeOf(this, BusinessError.prototype);
}
}Вывод: Создание пользовательских типов ошибок позволяет структурировать обработку исключений, добавлять контекстную информацию и создавать понятную иерархию ошибок для лучшего управления ошибками в приложении.