npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rsnk/result

v1.0.0

Published

A TypeScript port of Rust's Result<T, E> type, providing a type-safe way to handle errors and avoid exceptions.

Downloads

124

Readme

Result

NPM Version NPM License NPM Downloads Bundle Size

A TypeScript port of Rust's Result<T, E> type, providing a type-safe way to handle errors and avoid exceptions.

Table of Contents

Installation

Install the package using your favorite package manager:

npm install @rsnk/result

or

yarn add @rsnk/result

Overview

The Result type represents either success (Ok) or failure (Err). This pattern eliminates the ambiguity of throwing exceptions and makes error handling explicit and type-safe.

// Instead of this:
try {
  const user = getUser(id);
  console.log(user.name);
} catch (e) {
  console.error("Failed:", e);
}

// Write this:
const result = getUser(id); // Result<User, Error>
result.match({
  Ok: user => console.log(user.name),
  Err: err => console.error("Failed:", err)
});

Quick Start

import R from "@rsnk/result";

Creating Results

// Create a success (Ok)
const success = R.ok(42);            // Result<number, never>

// Create a failure (Err)
const failure = R.err("not found");  // Result<never, string>

// Wrap a function that might throw
const res = R.tryCatch(() => JSON.parse(str)); // Result<any, unknown>

// Wrap a Promise
const asyncRes = await R.fromPromise(fetch("/api/data")); // Result<Response, unknown>

Basic Operations

// Check status
if (result.isOk()) {
  console.log(result.unwrap());
}

// Transform values
result
  .map(x => x * 2)
  .mapErr(err => `Error: ${err}`)
  .unwrapOr(0);

// Pattern matching
result.match({
  Ok: value => console.log("Success:", value),
  Err: error => console.error("Error:", error)
});

Common Patterns

Chaining Operations (Railway Oriented Programming)

Propagate errors automatically while applying transformations to successful values.

function getProcessedData(input: string): Result<number, string> {
  return parseInput(input)           // Result<Input, string>
    .andThen(validateInput)          // Result<Input, string>
    .map(processData)                // Result<Data, string>
    .map(data => data.value);        // Result<number, string>
}

Async Error Handling

Handle async operations without try-catch hell.

const result = await R.fromPromise(fetchUser(id))
  .andThenAsync(async user => await fetchPreferences(user.id))
  .map(prefs => prefs.theme);

Safe Unwrapping

Avoid throwing exceptions when accessing values.

// Safe defaults
const port = getConfig("port")
  .map(Number)
  .unwrapOr(8080);

// Computed defaults
const config = loadConfig()
  .unwrapOrElse(err => defaultConfig);

TypeScript Type Narrowing

The Result type integrates seamlessly with TypeScript's type system:

const res: Result<number, string> = someOperation();

// Type guards work automatically
if (res.isOk()) {
  const val: number = res.unwrap(); // Safe!
} else {
  const err: string = res.unwrapErr(); // Safe!
}

// Type predicates
if (res.isOkAnd(x => x > 10)) {
  // TypeScript knows it's Ok and potentially narrows type based on predicate
}

Comparison with Other Approaches

vs Exceptions

Exceptions:

  • Implicit control flow (GOTO).
  • Easy to forget to handle.
  • Function signatures don't reveal possible errors.

Result:

  • Explicit control flow.
  • Forced error handling (cannot access value without handling error).
  • Function signatures document success and failure types (Result<User, DatabaseError>).

vs Returning null/false

Returning null/false:

  • No error context (why did it fail?).
  • Ambiguous (is null a valid value or an error?).

Result:

  • Err contains rich error information.
  • Clear distinction between success value and error value.

Design Philosophy

This implementation prioritizes developer experience and productivity. Key design decisions:

  • Class-Based: For better IDE autocomplete and method chaining.
  • Separate Ok/Err Classes: Optimized for performance and clean implementation.
  • Heavy Async Support: First-class support for Promise integration (mapAsync, andThenAsync), as modern TS is heavily async.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

MIT

API Reference

Factory Functions

R.ok<T, E>(value: T): Result<T, E>

Creates a success Ok result.

R.err<E, T>(error: E): Result<T, E>

Creates a failure Err result.

R.tryCatch<T, E>(fn: () => T): Result<T, E>

Executes a function and returns Ok(value) or Err(error) if it throws.

R.fromPromise<T, E>(promise: Promise<T>): Promise<Result<T, E>>

Converts a Promise to a Result. Resolves to Ok or rejects to Err.

Type Checking

isOk(): this is Ok<T, E>

Returns true if the result is Ok.

isErr(): this is Err<T, E>

Returns true if the result is Err.

isOkAnd(predicate: (value: T) => boolean): boolean

Returns true if Ok and the predicate matches.

isErrAnd(predicate: (error: E) => boolean): boolean

Returns true if Err and the predicate matches.

Extraction (Unwrapping)

unwrap(): T

Returns the value. Throws if Err.

unwrapErr(): E

Returns the error. Throws if Ok.

expect(msg: string): T

Returns the value. Throws with message if Err.

unwrapOr<U>(default: U): T | U

Returns the value or a default.

unwrapOrElse<U>(fn: (err: E) => U): T | U

Returns the value or computes a default from the error.

Transformations

map<U>(fn: (val: T) => U): Result<U, E>

Transforms the Ok value.

mapErr<F>(fn: (err: E) => F): Result<T, F>

Transforms the Err value.

mapOr<U>(default: U, fn: (val: T) => U): U

Maps and unwraps, returning a default if Err.

mapOrElse<U>(defaultFn: (err: E) => U, fn: (val: T) => U): U

Maps and unwraps, computing default from error if Err.

flatten()

Flattens Result<Result<T, E>, E> to Result<T, E>.

Chaining

andThen<U>(fn: (val: T) => Result<U, E>): Result<U, E>

Chains operations that may fail (flatMap).

and<U>(res: Result<U, E>): Result<U, E>

Returns res if Ok, otherwise returns self (Err).

or<F>(res: Result<T, F>): Result<T, F>

Returns self if Ok, otherwise returns res.

orElse<F>(fn: (err: E) => Result<T, F>): Result<T, F>

Returns self if Ok, otherwise calls fn to recover from error.

Async

mapAsync<U>(fn: (val: T) => Promise<U>): Promise<Result<U, E>>

Async version of map.

andThenAsync<U>(fn: (val: T) => Promise<Result<U, E>>): Promise<Result<U, E>>

Async version of andThen.

transposePromise()

Converts Result<Promise<T>, E> to Promise<Result<T, E>>.

Side Effects

inspect(fn: (val: T) => void): Result<T, E>

Runs fn if Ok.

inspectErr(fn: (err: E) => void): Result<T, E>

Runs fn if Err.

Pattern Matching

match({ Ok: fn, Err: fn }): U

Pattern matching.