Zero-dependency, type-safe error handling inspired by Rust's Result type. Say goodbye to try-catch blocks and hello to elegant error handling!
- π Zero Dependencies - Lightweight and blazing fast
- πͺ Type Safe - Full TypeScript support with type inference
- π Universal - Works in Node.js, Bun, Deno, and browsers
- π¦ Tiny - Less than 300 bytes minified + gzipped
# npm
npm install rerust
# yarn
yarn add rerust
# pnpm
pnpm add rerust
# JSR registry
npx jsr add @jimfilippou/rerust
import { ok, err, isOk, type Result } from "rerust";
function divide(a: number, b: number): Result<number> {
if (b === 0) return err("Division by zero");
return ok(a / b);
}
const result = divide(10, 2);
if (isOk(result)) {
console.log("Result:", result.value);
} else {
console.error("Error:", result.value);
}
Traditional error handling in JavaScript/TypeScript often leads to verbose and nested try-catch blocks. ReRust provides a more elegant way to handle errors, inspired by Rust's Result type.
async function getUserData(userId: string) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error("Failed to fetch user");
}
const data = await response.json();
try {
validateUserData(data);
return data;
} catch (validationError) {
console.error("Validation failed:", validationError);
throw validationError;
}
} catch (error) {
console.error("Error fetching user:", error);
return null;
}
}
// Usage
async function handleUserProfile() {
try {
const userData = await getUserData("123");
if (userData === null) {
showError("Failed to load user");
return;
}
updateUI(userData);
} catch (error) {
showError("Something went wrong");
}
}
import { ok, err, isOk, isErr, type Result } from "rerust";
async function getUserData(userId: string): Promise<Result<UserData>> {
const response = await fetch(`/api/users/${userId}`)
.then((res) => (res.ok ? ok(res) : err("Failed to fetch user")))
.catch(() => err("Network error"));
if (isErr(response)) return response;
const data = await response.value.json();
const validationResult = validateUserData(data);
return isOk(validationResult) ? ok(data) : err("Invalid user data");
}
// Usage
async function handleUserProfile() {
const res = await getUserData("123");
if (isErr(res)) return showError(result.value); // Type-safe error message
updateUI(result.value);
}
import { ok, err, isOk, type Result } from "rerust";
type User = { id: string; name: string };
type Order = { id: string; items: string[] };
function findUser(id: string): Result<User> {
// Simulate database lookup
return id === "1" ? ok({ id: "1", name: "John" }) : err("User not found");
}
function getUserOrders(user: User): Result<Order[]> {
// Simulate order lookup
return ok([{ id: "order1", items: ["item1", "item2"] }]);
}
// Chain operations
function getUserWithOrders(
userId: string
): Result<{ user: User; orders: Order[] }> {
const userResult = findUser(userId);
if (isErr(userResult)) return userResult;
const ordersResult = getUserOrders(userResult.value);
if (isErr(ordersResult)) return ordersResult;
return ok({
user: userResult.value,
orders: ordersResult.value,
});
}
const result = ok({ name: "John", age: 30 });
// TypeScript knows `user` has `name` and `age` properties
if (isOk(result)) {
const user = result.value;
console.log(user.name); // TypeScript autocompletion works!
}
// TypeScript knows `error` is a string
if (isErr(result)) {
const error = result.value;
console.error(error.toUpperCase()); // TypeScript knows this is a string
}
type Result<T, E = string> =
| { success: true; value: T } // Ok variant
| { success: false; value: E }; // Err variant
ok<T>(value: T): Result<T>
- Creates a successful resulterr<E>(value: E): Result<never, E>
- Creates an error resultisOk<T, E>(result: Result<T, E>): boolean
- Type guard for successful resultsisErr<T, E>(result: Result<T, E>): boolean
- Type guard for error results
Contributions are welcome! Please feel free to submit a Pull Request.