Result Type Pattern
In this page:
Defining a Result Type
A Result type typically contains either an ok result carrying a value or an error result carrying an error value — success and failure become explicit data instead of something only discoverable via a thrown exception.
Example: Defining a Result Type
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
const success: Result<number, string> = { ok: true, value: 42 };
console.log(success);
Handling Success and Failure
Check the ok property before accessing value or error — this is exactly the shape TypeScript needs to safely narrow a discriminated union, so the compiler will actually stop you from reading value on a failed Result.
Example: Handling Success and Failure
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function divide(a: number, b: number): Result<number, string> {
return b === 0 ? { ok: false, error: "Division by zero" } : { ok: true, value: a / b };
}
const result = divide(10, 2);
if (result.ok) console.log(result.value);
else console.log(result.error);
Result with Custom Errors
The error side of a Result can hold a custom error class or any other structured error type, letting you carry as much detail about a failure as you want without resorting to throwing.
Example: Result with Custom Errors
class ValidationError extends Error {}
type Result<T> = { ok: true; value: T } | { ok: false; error: ValidationError };
function parseAge(input: string): Result<number> {
const n = Number(input);
return isNaN(n) ? { ok: false, error: new ValidationError("bad age") } : { ok: true, value: n };
}
console.log(parseAge("25"));
Result Helper Functions
Small helper functions — ok(value) and err(error) — make Result values quick to construct and keep call sites readable instead of manually building the object literal every time.
Example: Result Helper Functions
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function ok<T>(value: T): Result<T, never> { return { ok: true, value }; }
function err<E>(error: E): Result<never, E> { return { ok: false, error }; }
console.log(ok(5), err("failed"));
When to Use Result
Result shines when failures are expected, routine outcomes — a validation failure, a not-found lookup — and callers should be forced to handle them explicitly rather than being able to ignore a thrown exception.
Example: When to Use Result
type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
function findUser(id: number): Result<string, string> {
return id === 1 ? { ok: true, value: "Ravi" } : { ok: false, error: "not found" };
}
const result = findUser(2);
console.log(result.ok ? result.value : result.error);
Chapter Quiz — Complete all 5 topics to unlock
0/5 topics done
Complete these topics first: