Lab 08: Error Handling
Objective
Time
Prerequisites
Tools
Lab Instructions
Step 1: Typed Error Classes
// Custom error hierarchy
class AppError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly context?: Record<string, unknown>,
) {
super(message);
this.name = this.constructor.name;
// Fix prototype chain (needed for `instanceof`)
Object.setPrototypeOf(this, new.target.prototype);
}
}
class ValidationError extends AppError {
constructor(
public readonly field: string,
message: string,
public readonly value?: unknown,
) {
super(message, "VALIDATION_ERROR", { field, value });
}
}
class NotFoundError extends AppError {
constructor(resource: string, id: number | string) {
super(`${resource} #${id} not found`, "NOT_FOUND", { resource, id });
}
}
class NetworkError extends AppError {
constructor(url: string, public readonly statusCode: number) {
super(`HTTP ${statusCode} from ${url}`, "NETWORK_ERROR", { url, statusCode });
}
}
// Usage
function processAge(input: string): number {
const age = parseInt(input);
if (isNaN(age)) throw new ValidationError("age", `'${input}' is not a number`, input);
if (age < 0 || age > 150) throw new ValidationError("age", `Age ${age} out of range`, age);
return age;
}
["25", "abc", "-1", "200"].forEach(input => {
try {
console.log(`age=${processAge(input)}`);
} catch (e) {
if (e instanceof ValidationError) {
console.log(`ValidationError[${e.field}]: ${e.message}`);
} else {
throw e;
}
}
});Step 2: Result Type Pattern
Steps 3–8: Either Type, Error Boundaries, Async Errors, Exhaustive, Retry, Capstone
Summary
Further Reading
Last updated
