S SmartDocs
Serie: Typescript typescript 122 líneas · Actualizado 2025-12-27

10-error-handling.ts

Typescript/src/02-intermediate/10-error-handling.ts

// ============================================
// 10. Error Handling
// ============================================

// Result Pattern
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

function divide(a: number, b: number): Result<number> {
  if (b === 0) {
    return { success: false, error: new Error("Division by zero") };
  }
  return { success: true, data: a / b };
}

const result = divide(10, 2);
if (result.success) {
  console.log(result.data); // TypeScript knows data exists
} else {
  console.error(result.error); // TypeScript knows error exists
}

// Option/Maybe Pattern
type Option<T> = T | null;

function findUser(id: string, users: Array<{ id: string; name: string }>): Option<{ id: string; name: string }> {
  return users.find(u => u.id === id) ?? null;
}

const users = [
  { id: "1", name: "Alice" },
  { id: "2", name: "Bob" }
];

const user = findUser("1", users);
if (user) {
  // TypeScript knows user is not null
  console.log(user.name);
}

// Better Option Type
type Some<T> = { kind: "some"; value: T };
type None = { kind: "none" };
type Option2<T> = Some<T> | None;

function findUser2(id: string, users: Array<{ id: string; name: string }>): Option2<{ id: string; name: string }> {
  const user = users.find(u => u.id === id);
  return user ? { kind: "some", value: user } : { kind: "none" };
}

const result2 = findUser2("1", users);
if (result2.kind === "some") {
  console.log(result2.value.name); // TypeScript knows value exists
}

// Try-Catch with Types
function riskyOperation(): string {
  // Might throw
  return "result";
}

try {
  const result = riskyOperation();
  // result is string
  console.log(result);
} catch (error) {
  // error is unknown, not any
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error("Unknown error");
  }
}

// Custom Error Classes
class ValidationError extends Error {
  constructor(
    message: string,
    public field: string,
    public value: any
  ) {
    super(message);
    this.name = "ValidationError";
  }
}

class NetworkError extends Error {
  constructor(
    message: string,
    public statusCode: number
  ) {
    super(message);
    this.name = "NetworkError";
  }
}

type AppError = ValidationError | NetworkError;

function handleError(error: AppError) {
  if (error instanceof ValidationError) {
    console.error(`Validation failed for ${error.field}: ${error.message}`);
  } else if (error instanceof NetworkError) {
    console.error(`Network error ${error.statusCode}: ${error.message}`);
  }
}

// Assertion Functions for Errors
function assert(condition: boolean, message: string): asserts condition {
  if (!condition) {
    throw new Error(message);
  }
}

function process(value: string | null) {
  assert(value !== null, "Value cannot be null");
  // TypeScript knows value is string here
  console.log(value.length);
}

export { divide, findUser, handleError, process };

Artículos relacionados