https://github.com/brettchalupa/result
Type-safe Result pattern for TypeScript, inspired by Rust
https://github.com/brettchalupa/result
bun deno error-handling functional-programming jsr monads result rust-inspired type-safe typescript
Last synced: about 1 month ago
JSON representation
Type-safe Result pattern for TypeScript, inspired by Rust
- Host: GitHub
- URL: https://github.com/brettchalupa/result
- Owner: brettchalupa
- License: unlicense
- Created: 2025-10-22T01:01:02.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-10-22T11:47:02.000Z (8 months ago)
- Last Synced: 2025-11-02T04:03:15.684Z (7 months ago)
- Topics: bun, deno, error-handling, functional-programming, jsr, monads, result, rust-inspired, type-safe, typescript
- Language: TypeScript
- Homepage:
- Size: 26.4 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# @brettchalupa/result
A TypeScript library implementing the Result pattern for type-safe error
handling, inspired by Rust's `Result`.
View the package on JSR: https://jsr.io/@brettchalupa/result
## Why?
Traditional `try/catch` error handling in TypeScript is painful:
- ❌ **Invisible control flow** - Can't tell which functions throw by looking at
signatures
- ❌ **No type safety** - Caught errors are `unknown`, TypeScript can't help you
- ❌ **Difficult to test** - Easy to miss error paths and leave them untested
- ❌ **Unclear propagation** - Hard to tell where errors originate when they
bubble up
**Result makes errors explicit:**
```typescript
// ❌ Exception-based: Which functions throw? What error types?
function processUser(id: string): User {
const user = findUser(id); // Throws? Maybe?
return validateUser(user); // Throws? Who knows?
}
// ✅ Result-based: Clear from the signature what can fail
function processUser(id: string): Result {
const user = findUser(id); // Returns Result
return user.andThen(validateUser); // Type-safe chaining!
}
```
With Result, **errors are just values** - visible in the type system, easy to
handle, and impossible to ignore accidentally.
## Features
- **Type-safe error handling** - Errors are part of the function signature
- **Method chaining** - Fluent API for transforming and combining results
- **Zero dependencies** - Lightweight and fast
- **Full TypeScript support** - Complete type inference and safety
- **Well tested** - Comprehensive test suite with 50+ tests
## Installation
```bash
# Deno
deno add jsr:@brettchalupa/result
# pnpm 10.9+
pnpm add jsr:@brettchalupa/result
# yarn 4.9+
yarn add jsr:@brettchalupa/result
# npm, bun, and older versions of yarn or pnpm
npx jsr add @brettchalupa/result # replace npx with any of yarn dlx, pnpm dlx, or bunx
```
Or import directly in Deno without installation:
```typescript
import { err, ok, Result } from "jsr:@brettchalupa/result";
const result = ok(42);
```
## Quick Start
```typescript
import { err, ok, type Result } from "@brettchalupa/result";
function divide(a: number, b: number): Result {
if (b === 0) {
return err("Cannot divide by zero");
}
return ok(a / b);
}
const result = divide(10, 2);
if (result.isOk()) {
console.log("Result:", result.data); // Result: 5
} else {
console.error("Error:", result.error);
}
```
## Usage
### Basic Results
Create successful or failed results:
```typescript
import { err, ok } from "@brettchalupa/result";
// Success
const success = ok(42);
console.log(success.data); // 42
// Failure
const failure = err("Something went wrong");
console.log(failure.error); // "Something went wrong"
```
### Method Chaining
Transform results with a fluent API:
```typescript
const result = ok(5)
.map((x) => x * 2)
.map((x) => x.toString()); // ok("10")
const error = err("not_found").mapErr((code) => ({
code,
message: "Resource not found",
}));
```
### Handling Async Operations
```typescript
import { Result } from "@brettchalupa/result";
// Wrap throwing code
const parsed = Result.try(() => JSON.parse(jsonString));
// Wrap async operations
const data = await Result.tryAsync(() => fetch(url).then((r) => r.json()));
```
### Combining Results
```typescript
import { err, ok, Result } from "@brettchalupa/result";
// Collect all successes or get first error
const results = [ok(1), ok(2), ok(3)];
const combined = Result.all(results); // ok([1, 2, 3])
// Partition successes and failures
const mixed = [ok(1), err("error"), ok(3)];
const [successes, failures] = Result.partition(mixed);
// successes: [1, 3]
// failures: ["error"]
```
### Repository Pattern
```typescript
import { err, ok, type Result } from "@brettchalupa/result";
type User = { id: string; name: string };
// Define your own domain-specific error types
type DbError = "NOT_FOUND" | "CONNECTION_ERROR" | "PERMISSION_DENIED";
async function findUser(id: string): Promise> {
try {
const user = await db.findOne({ id });
if (!user) {
return err("NOT_FOUND");
}
return ok(user);
} catch (error) {
return err("CONNECTION_ERROR");
}
}
```
## API Reference
### Constructors
- `ok(data: T): Ok` - Create a successful result
- `err(error: E): Err` - Create a failed result
### Instance Methods
Both `Ok` and `Err` types support:
- `.isOk()` - Type guard for success
- `.isErr()` - Type guard for failure
- `.map(fn)` - Transform the success value
- `.mapErr(fn)` - Transform the error value
- `.andThen(fn)` - Chain operations that return Results
- `.unwrapOr(defaultValue)` - Get value or default
- `.unwrap()` - Get value or throw
- `.expect(message)` - Get value or throw with message
### Utility Functions
The `Result` namespace provides:
- `Result.try(fn)` - Wrap a throwing function
- `Result.tryAsync(fn)` - Wrap an async throwing function
- `Result.all(results)` - Combine results
- `Result.partition(results)` - Separate successes and failures
- `Result.collectErrors(results)` - Get all errors
- `Result.map(result, fn)` - Static map function
- `Result.mapErr(result, fn)` - Static mapErr function
- `Result.andThen(result, fn)` - Static andThen function
- `Result.unwrapOr(result, default)` - Static unwrapOr function
- `Result.unwrap(result)` - Static unwrap function
- `Result.expect(result, message)` - Static expect function
## Development
```bash
# Run tests
deno test
# Run all checks (format, lint, type check, test)
deno task ok
# Watch mode
deno task dev
```
## License
This is free and unencumbered software released into the public domain. See
[UNLICENSE](./UNLICENSE) for details.
## Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.