A robust, type-safe error handling library for TypeScript that closely mirrors Rust's error handling patterns. This library helps you write more reliable code by making error handling explicit and leveraging TypeScript's type system to catch errors at compile time.
- π¦ Rust-like
Result<T, E>
type for explicit error handling - π Type-safe validation types for common use cases
- β‘ Full async support with
ResultAsync<T, E>
- π‘οΈ Comprehensive error type system
- π¨ Panic system for unrecoverable errors
- π Extensive documentation and examples
# Using bun
bun add rust-errors
# Using npm
npm install rust-errors
# Using yarn
yarn add rust-errors
import { type Result, ok, err, match } from 'rust-errors';
function divide(a: number, b: number): Result<number, string> {
if (b === 0) {
return err('Division by zero');
}
return ok(a / b);
}
// Using pattern matching
match(
divide(10, 2),
(value) => console.log('Result:', value),
(error) => console.error('Error:', error),
);
// Using unwrap (throws if error)
try {
const result = divide(10, 0).unwrap();
console.log('Result:', result);
} catch (e) {
console.error('Error:', e);
}
import {
type Result,
NonEmptyString,
EmailAddress,
RangeNumber,
ValidationError,
} from 'rust-errors';
// Validate a non-empty string
const name = NonEmptyString.create('John Doe');
if (name.isOk()) {
console.log('Valid name:', name.unwrap().toString());
}
// Validate an email address
const email = EmailAddress.create('invalid-email');
if (email.isErr()) {
console.error('Invalid email:', email.err()?.message);
}
// Validate a number in range
const age = RangeNumber.create(25, 0, 120);
if (age.isOk()) {
console.log('Valid age:', age.unwrap().valueOf());
}
import {
type ResultAsync,
toResultAsync,
NetworkError,
andThenAsync,
} from 'rust-errors';
async function fetchUser(id: number): ResultAsync<User, NetworkError> {
return toResultAsync(
fetch(`/api/users/${id}`).then((res) => res.json()),
(error) => new NetworkError('Failed to fetch user', error),
);
}
// Chain async operations
const userAndPosts = await andThenAsync(
fetchUser(1),
async (user) => fetchUserPosts(user.id),
);
if (userAndPosts.isOk()) {
const posts = userAndPosts.unwrap();
console.log('User posts:', posts);
}
import { type Result, ok, err, ValidationError } from 'rust-errors';
class PostalCode {
private constructor(private readonly value: string) {}
static create(value: string): Result<PostalCode, ValidationError> {
const pattern = /^\d{5}(-\d{4})?$/;
if (!pattern.test(value)) {
return err(new ValidationError('Invalid postal code format'));
}
return ok(new PostalCode(value));
}
toString(): string {
return this.value;
}
}
const postalCode = PostalCode.create('12345-6789');
if (postalCode.isOk()) {
console.log('Valid postal code:', postalCode.unwrap().toString());
}
import {
NetworkError,
ValidationError,
TimeoutError,
ParseError,
} from 'rust-errors';
// Network error with status code
const networkError = new NetworkError('API request failed', 404);
// Validation error with cause
const validationError = new ValidationError(
'Invalid input',
new Error('Value out of range'),
);
// Timeout error with duration
const timeoutError = new TimeoutError('Operation timed out', 5000);
// Parse error
const parseError = new ParseError('Failed to parse JSON');
import { panic, assert, unreachable, configurePanic } from 'rust-errors';
// Configure panic behavior
configurePanic({
includeStackTrace: true,
handler: (message, error) => {
console.error('Fatal error:', message);
process.exit(1);
},
});
// Assert conditions
function sqrt(n: number): number {
assert(n >= 0, 'Number must be non-negative');
return Math.sqrt(n);
}
// Mark unreachable code
function processValue(value: 'A' | 'B'): string {
switch (value) {
case 'A':
return 'Value is A';
case 'B':
return 'Value is B';
default:
return unreachable('All cases should be handled');
}
}
Check out the examples directory for more detailed examples:
For detailed API documentation, see the API docs.
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.