What is Result?
Result.js implements Rust's Result<T, E> pattern for JavaScript/TypeScript, providing explicit, type-safe error handling without exceptions.
The Result Type
Result<T, E> represents an operation that can either succeed or fail:
typescript
type Result<T, E> = Ok<T, E> | Err<T, E>Ok<T>— contains a success valueErr<E>— contains an error value
Result vs Exception-Based Error Handling
| Aspect | Exception | Result |
|---|---|---|
| Error visibility | Hidden in types | Explicit in signature |
| Compiler enforcement | None | Enforced by TypeScript |
| Composition | Nested try-catch | Fluent chaining |
| Recovery | Limited patterns | Pattern matching |
| Performance | Stack unwinding | Zero overhead |
Example: Before and After
With Exceptions
typescript
function divide(a: number, b: number): number {
if (b === 0) throw new Error('Division by zero')
return a / b
}
try {
const result = divide(10, 0)
console.log(result)
} catch (error) {
console.error(error) // error type is unknown
}With Result
typescript
function divide(a: number, b: number): Result<number, string> {
if (b === 0) return Result.err('Division by zero')
return Result.ok(a / b)
}
const result = divide(10, 0)
result.match({
ok: (val) => console.log(val),
err: (msg) => console.error(msg) // error type is explicit: string
})Key Characteristics
Immutability
All operations return new Results — originals are never modified:
typescript
const original = Result.ok(5)
const doubled = original.map(x => x * 2)
console.log(original.unwrap()) // 5 (unchanged)
console.log(doubled.unwrap()) // 10Explicit Error Handling
Results make failures visible in the type signature. While unwrap() is available, calling it on an Err throws at runtime — the pattern encourages handling both cases explicitly:
typescript
const result: Result<number, string> = divide(10, 0)
// ✗ Unsafe: throws at runtime if result is Err
const value = result.unwrap()
// ✓ Safe: check state first, TypeScript narrows the type
if (result.isOk()) {
const value = result.unwrap() // Ok<number, string> — safe
}
// ✓ Preferred: pattern matching forces handling both cases
result.match({
ok: (val) => console.log(val),
err: (err) => console.error(err)
})When to Use Result
Use Result for:
- Expected errors (validation, not found, parsing failures)
- Business logic failures (permission denied, insufficient funds)
- Recoverable failures (network timeout, cache miss)
- APIs where errors are common
Use exceptions for:
- Unexpected errors (out of memory, programmer mistakes)
- Fatal errors that cannot be recovered from
Core Methods Reference
| Method | Purpose |
|---|---|
Result.ok(value) | Create success Result |
Result.err(error) | Create failure Result |
result.isOk() | Check if Ok |
result.isErr() | Check if Err |
result.unwrap() | Extract value (throws at runtime if Err) |
result.unwrapOr(def) | Extract with default |
result.map(fn) | Transform success value |
result.andThen(fn) | Chain operations |
result.match({ok, err}) | Handle both cases |
For the complete API, see API Reference.
Next Steps
- Installation — Set up in your project
- Quick Start — Practical examples