CodePark/ questions / Error handling & API boundaries
START PRACTICINGPRACTICE
Backend question · Software design & patterns › Error handling & API boundaries

Compare throwing exceptions with returning a Result<T, E> type in TypeScript. When would you use each?

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

function parseAge(input: string): Result<number, "NotANumber" | "Negative"> {
  const n = Number(input);
  if (Number.isNaN(n)) return { ok: false, error: "NotANumber" };
  if (n < 0) return { ok: false, error: "Negative" };
  return { ok: true, value: n };
}

Use a Result type for expected business failures, and use exceptions for unexpected failures.

Exceptions don't appear in TypeScript signatures. Nothing tells the caller that placeOrder() can throw OutOfStockError. Also, catch gives you a value of type unknown. Exceptions are useful for failures the caller can't really handle. They travel up the call stack on their own to a top-level handler.

A Result type is a discriminated union, like the one above. It makes expected failures part of the return type. The compiler forces callers to check ok before they use value. The error cases are typed, and the compiler can check that you handle all of them. The cost: each call site has more code, and you need helper functions to chain results.

A common split:

  • Use Result (or typed error unions) for expected business outcomes, such as a validation failure, insufficient funds or "not found".
  • Use exceptions for unexpected or infrastructure failures, such as a lost database connection or a bug. Let them go up to a global handler.

Whatever you choose, use it the same way across the whole codebase.

  • Exceptions are not in the TypeScript type signature, and catch gives you unknown.
  • A Result type makes expected failures explicit, and the compiler checks them.
  • A Result type adds extra code at every call site.
  • Use Result for expected business outcomes and exceptions for unexpected failures.
  • Pick one convention for the whole codebase.