Skip to content

Zero-dependency, Rust-inspired error handling for TypeScript

License

Notifications You must be signed in to change notification settings

jimfilippou/rerust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

8 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

rerust

npm version JSR Bundle Size License: MIT TypeScript No Dependencies

Zero-dependency, type-safe error handling inspired by Rust's Result type. Say goodbye to try-catch blocks and hello to elegant error handling!

Features

  • πŸš€ 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

Installation

# npm
npm install rerust

# yarn
yarn add rerust

# pnpm
pnpm add rerust

# JSR registry
npx jsr add @jimfilippou/rerust

Usage

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);
}

Sponsors

Why ReRust?

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.

Before ReRust

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");
  }
}

After ReRust

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);
}

Advanced Usage

Chaining Results

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,
  });
}

Type Guards

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
}

API Reference

Types

type Result<T, E = string> =
  | { success: true; value: T } // Ok variant
  | { success: false; value: E }; // Err variant

Functions

  • ok<T>(value: T): Result<T> - Creates a successful result
  • err<E>(value: E): Result<never, E> - Creates an error result
  • isOk<T, E>(result: Result<T, E>): boolean - Type guard for successful results
  • isErr<T, E>(result: Result<T, E>): boolean - Type guard for error results

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

About

Zero-dependency, Rust-inspired error handling for TypeScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published