8000 GitHub - fuzzy-st/results: 🤓 A lightweight `Result<T,E>` Library which provides a set of robust and type-safe functions to represent operations that can either **succeed** or **fail** without relying on exception handling 🤓
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
generated from fuzzy-st/errors

🤓 A lightweight `Result<T,E>` Library which provides a set of robust and type-safe functions to represent operations that can either **succeed** or **fail** without relying on exception handling 🤓

License

Notifications You must be signed in to change notification settings

fuzzy-st/results

Repository files navigation

Result Pattern

npm GitHub npm bundle size npm type definitions

A highly optimized, fully type-safe, dependency-free utility for representing operations that can either succeed or fail.

Complete with:

  • Comprehensive functional transformations
  • Advanced error handling capabilities
  • Async/Promise integration
  • Performance optimizations
  • Elegant composition patterns

Its a fuzzy approach where by having better results we can craft more reliable code that doesn't rely on try/catch and exceptions for control flow.

🔍 Overview

This library aims to provide an elegant solution for handling operations that can succeed or fail in TypeScript applications. It addresses the common problems with traditional exception-based error handling while maintaining full type safety and composability.

Unlike traditional error handling with exceptions, this library seeks to enable us with the following:

  • Explicit error handling with proper type information
  • Composable operations that might fail
  • Functional transformations of success and error values
  • Predictable control flow without hidden exceptional paths
  • Better testability through deterministic error handling
  • Performance optimizations for high-throughput scenarios

✨ Features

  • 🧙‍♂️ Type-Safe Results - Experience bulletproof type safety with full TypeScript inference and precise error typing. No more "any" type nightmares or runtime surprises.

  • 🔄 Powerful Functional Transformations - Transform your data with elegant, chainable operations like map, chain, and pipe. Build complex processing flows with minimal code.

  • 👪 Painless Composition - Compose operations that might fail without deeply nested try/catch blocks. Create clean, readable code that's easy to maintain and extend.

  • 🧬 First-Class Async Support - Handle async operations with the same elegant API. Convert Promises to Results, chain async operations, and process multiple async results in parallel.

  • ⚠️ Explicit Error Handling - Say goodbye to forgotten try/catch blocks and silent failures. Every potential error becomes a value you can inspect, transform, and handle with precision.

  • 😇 Control Your Own Destiny - Decide exactly when and how to extract values from results with smart unwrapping operations that prevent runtime crashes.

  • 🚂 Railway-Oriented Programming - Implement the powerful railway pattern with built-in short-circuiting. Keep your happy path clean while ensuring errors naturally flow to error handlers.

  • Blazing Fast Performance - Meticulously optimized for speed and minimal memory usage. We've benchmarked extensively to ensure near-zero overhead compared to traditional error handling.

  • 🤑 Rich Combinators - Combine multiple results with sophisticated utilities like asyncAll and sophisticated error aggregation. No more manual result merging.

  • 💻 Developer Experience First - Designed for humans with clear naming, consistent behavior, and detailed documentation with practical examples for every function.

  • 🆓 Zero Dependencies - Not a single external dependency. Just pure, optimized TypeScript that won't bloat your bundle or introduce security vulnerabilities.

  • 💚 Universal Compatibility - Works anywhere JavaScript runs: browsers, Node.js, Deno, Bun, web workers, or serverless functions. One API to rule them all.

  • 🪖 Battle-Tested - Comprehensive guides with real-world examples for every function. Learn through practical code, not just abstract theory.

🚀 Installation

# Using npm
npm install @fuzzy-street/results

# Using yarn
yarn add @fuzzy-street/results

# Using pnpm
pnpm add @fuzzy-street/results

🔍 Core Concepts

Result Pattern is built around a simple concept: a function that can either succeed or fail returns a Result<T, E> type, which is either:

  • { status: "success", data: T } for successful operations
  • { status: "error", error: E } for failed operations

This allows you to:

  1. Make error handling explicit and type-safe
  2. Create pipelines of operations where errors naturally short-circuit
  3. Eliminate try/catch blocks for control flow
  4. Ensure all error cases are handled

🧩 Basic Usage

import { success, error, isSuccess, isError, match } from '@fuzzy-street/results';

// Creating success results
const successResult = success(42);
// { status: "success", data: 42 }

// Creating error results
const errorResult = error(new Error('Something went wrong'));
// { status: "error", error: Error("Something went wrong") }

// Type checking
if (isSuccess(successResult)) {
  console.log(successResult.data); // 42
}

if (isError(errorResult)) {
  console.log(errorResult.error.message); // "Something went wrong"
}

// Pattern matching
const message = match(successResult, {
  success: (value) => `Success: ${value}`,
  error: (err) => `Error: ${err.message}`
});
// "Success: 42"

📚 Library Structure

The library is organized into three main categories:

Core Functions

These form the foundation of the Result pattern:

  • success: Creates a successful result
  • error: Creates an error result
  • isSuccess: Type guard for successful results
  • isError: Type guard for error results
  • isResult: Type guard for any result
  • match: Pattern matching for results
  • unwrap: Extracts value or throws error
  • unwrapOr: Extracts value with fallback

Transformer Functions

These help transform and process results:

  • map: Transforms success values
  • mapError: Transforms error values
  • chain: Chains operations that might fail
  • tap: Performs side effects on any result
  • tapSuccess: Performs side effects on success results
  • tapError: Performs side effects on error results
  • pipe: Creates transformation pipelines
  • createErrorBoundary: Creates error-handling boundaries

Async Functions

These handle asynchronous operations:

Each function has detailed documentation and examples in the linked markdown files. We highly recommend exploring these docs to understand the full capabilities of each utility.

🌟 Advanced Examples

Railway-Oriented Programming

import { pipe, success, error } from '@fuzzy-street/results';

function validateInput(input: string) {
  return input ? success(input) : error(new Error('Input required'));
}

function processInput(input: string) {
  return input.length >= 3 
    ? success(input.toUpperCase()) 
    : error(new Error('Input too short'));
}

function formatOutput(input: string) {
  return success(`Processed: ${input}`);
}

// Create a processing pipeline
const result = pipe(
  'hello',               // Input value
  validateInput,         // Validate (short-circuit if invalid)
  processInput,          // Process (short-circuit if fails)
  formatOutput           // Format output
);

// result: { status: "success", data: "Processed: HELLO" }

Async Operations

import { asyncChain, fromPromise } from '@fuzzy-street/results';

async function fetchUser(id: string) {
  return fromPromise(
    fetch(`https://api.example.com/users/${id}`)
      .then(response => {
        if (!response.ok) throw new Error(`HTTP error ${response.status}`);
        return response.json();
      })
  );
}

async function fetchUserPosts(user) {
  return fromPromise(
    fetch(`https://api.example.com/users/${user.id}/posts`)
      .then(response => {
        if (!response.ok) throw new Error(`HTTP error ${response.status}`);
        return response.json();
      })
  );
}
    
// Chain async operations
async function getUserWithPosts(userId: string) {
  const userResult = await fetchUser(userId);
  return await asyncChain(userResult, fetchUserPosts);
}

Error Handling

import { match, success, error } from '@fuzzy-street/results';

function divideNumbers(a: number, b: number) {
  return b !== 0 
    ? success(a / b) 
    : error(new Error('Division by zero'));
}

const result = divideNumbers(10, 0);

// Pattern matching for elegant error handling
const message = match(result, {
  success: (value) => `Result: ${value}`,
  error: (err) => `Error: ${err.message}`
});

// message: "Error: Division by zero"

⚡Performance

The Result pattern has been carefully optimized to minimize overhead:

  • Minimal object creation in transformations
  • Early short-circuiting to avoid unnecessary processing
  • Efficient memory usage with optimized data structures
  • Benchmarks show minimal overhead compared to direct function calls

According to our benchmarks:

  • Function call overhead is acceptable for most real-world use cases
  • Error handling with Results is actually faster than traditional try/catch in many scenarios
  • Memory overhead is minimal

🧙‍♂️ TypeScript Support

This library is built with TypeScript first in mind:

  • Full type inference for all operations
  • Generic type parameters for flexible usage
  • Type guards for runtime type checking
  • Type narrowing for improved developer experience

🧪 Running Examples

This repository comes with a comprehensive set of examples to demonstrate the usage of each function. To run them locally:

  1. Clone the repository:

    git clone https://github.com/fuzzy-st/results.git
    cd results
  2. Install dependencies:

    pnpm install
  3. Run a specific example:

    pnpm tsx src/examples/core/success.ts
    pnpm tsx src/examples/transformers/pipe.ts
    pnpm tsx src/examples/async/asyncChain.ts

Each example file contains multiple usage patterns. To try a specific example, uncomment the corresponding run...() function at the bottom of the file before running it.

For example, in src/examples/core/success.ts:

// Uncomment any of these to run the example
// runBasicExample();
// runValidationExample();
runComplexExample(); // This one will execute

We encourage you to explore these examples to get a feel for how the library works in practice. Each example corresponds to the documentation for its respective function.

🤝 Contributing

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

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

About

🤓 A lightweight `Result<T,E>` Library which provides a set of robust and type-safe functions to represent operations that can either **succeed** or **fail** without relying on exception handling 🤓

Resources

License

Stars

Watchers

Forks

Languages

0