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 🙏

© 2025 – Pkg Stats / Ryan Hefner

go-result

v0.2.1

Published

Lightweight Go-style error handling for TypeScript

Readme

Go Result

go-result

Lightweight Go-style error handling for TypeScript

npm version npm downloads bundle size license TypeScript

The simplest Result type library for TypeScript. Shorter and more intuitive than Effect.js or neverthrow.

InstallationQuick StartWhy Explicit Errors?AI-FriendlyAPIComparison


Installation

npm install go-result

Quick Start

import { ok, err, type Result } from "go-result";

function divide(a: number, b: number): Result<number, string> {
  if (b === 0) {
    return err("division by zero");
  }
  return ok(a / b);
}

// Destructure and check error
const [value, error] = divide(10, 2);
if (error) {
  console.error("Error:", error);
  return;
}
console.log("Result:", value); // Result: 5

Go-style Error Handling

go-result brings Go's elegant error handling pattern to TypeScript:

// Go
value, err := divide(10, 2)
if err != nil {
    return err
}
fmt.Println(value)
// go-result (TypeScript)
const [value, err1] = divide(10, 2);
if (err1) {
  return err(err1);
}
console.log(value);

Nearly identical syntax and flow!

Why Explicit Error Handling?

The Problem with try-catch

Traditional try-catch in TypeScript has several issues:

// ❌ Problems with try-catch:
function divide(a: number, b: number): number {
  if (b === 0) {
    throw new Error("division by zero");  // 1. Not visible in type signature
  }
  return a / b;
}

// Caller has no idea this can throw!
const result = divide(10, 0);  // 2. Easy to forget error handling
console.log(result);  // 3. Runtime crash

Issues:

  1. Invisible errors: Function signature doesn't show it can fail
  2. Easy to forget: No compiler reminder to handle errors
  3. Runtime crashes: Unhandled exceptions crash your app
  4. Hard to trace: Exception stack traces can be misleading
  5. Performance: Try-catch blocks prevent JS engine optimizations

Modern Languages Choose Explicit Errors

Many modern languages have moved away from exceptions:

  • Go: Returns (value, error) tuples
  • Rust: Uses Result<T, E> enum
  • Swift: Uses Result<Success, Failure>
  • Zig: Explicit error unions
  • OCaml/F#: Result type
  • Scala: Either and Try

Why? Explicit error handling makes code more reliable, maintainable, and self-documenting.

go-result Makes Errors Explicit

// ✅ With go-result:
function divide(a: number, b: number): Result<number, string> {
  if (b === 0) {
    return err("division by zero");  // 1. Error is in the type!
  }
  return ok(a / b);
}

// Type signature forces you to handle errors
const [value, error] = divide(10, 0);  // 2. Compiler reminds you
if (error) {
  console.error(error);  // 3. Explicit handling
  return;
}
console.log(value);  // 4. Safe to use

Benefits:

  • ✅ Errors are visible in types
  • ✅ Compiler forces handling
  • ✅ No runtime crashes
  • ✅ Better performance (no try-catch overhead)
  • ✅ Self-documenting code

AI-Friendly Design

go-result is designed to be extremely simple for both humans and AI. LLMs can generate go-result code with minimal hallucination because there's almost no API to remember.

Perfect for VIBE Coding

When coding with AI assistants (Cursor, GitHub Copilot, Claude, etc.), error handling is often incomplete or incorrect. go-result solves this.

Simply give your AI this rule:

Rule for AI: When writing functions that can fail, ALWAYS use go-result. Wrap any error-prone operations (file I/O, network calls, parsing, etc.) with this library. Return Result<Success, Error> and handle errors with destructuring.

Example AI prompt:

Use go-result library for all error handling.
Any function that can fail must return Result<T, E>.
Always destructure with [value, error] and check error first.

For AI/LLM Code Generation

Rules:

  1. Import the library

    import { ok, err, type Result } from "go-result";
  2. Wrap ALL error-prone functions

    // ✅ Any operation that can fail MUST be wrapped
    function parseJSON(input: string): Result<any, string> {
      try {
        return ok(JSON.parse(input));
      } catch (e) {
        return err(`Invalid JSON: ${e.message}`);
      }
    }
    
    async function fetchUser(id: string): Result<User, string> {
      try {
        const response = await fetch(`/api/users/${id}`);
        if (!response.ok) return err(`HTTP ${response.status}`);
        const user = await response.json();
        return ok(user);
      } catch (e) {
        return err(`Network error: ${e.message}`);
      }
    }
  3. Always use destructuring pattern

    const [data, error] = parseJSON(input);
    if (error) return err(error);  // Early return on error
    // data is type-safe here

Why this works for AI:

  • Simple pattern that LLMs rarely hallucinate
  • Forces explicit error handling at every step
  • Type system catches missing error checks
  • Even in VIBE coding, your errors are handled correctly

That's it. No methods, no pipes, no runtime overhead. Just tuples and if statements.

API

ok<S>(value: S): readonly [S, null]

Creates a success result tuple.

const result = ok(42);
// result: readonly [42, null]

err<E>(error: E): readonly [null, E]

Creates an error result tuple.

const result = err("something went wrong");
// result: readonly [null, 'something went wrong']

Result<S, E>

Type representing either success or error.

type Result<S, E> = readonly [S, null] | readonly [null, E];

Usage Patterns

1. Early Return Pattern (Most Common)

// Propagate error up the call stack immediately
const [value, err1] = divide(10, 2);
if (err1) return err(err1); // Early return on error
console.log(value); // Type-safe: value is guaranteed to be number here

2. Error Handling Pattern

// Handle error with custom logic
const [value, err1] = divide(10, 0);
if (err1) {
  console.error("Division failed:", err1); // Log the error
  return; // Or throw, or return default value, etc.
}
console.log(value);

3. Success-only Pattern

// Only care about successful values
const [value] = divide(10, 2);
if (value) {
  console.log("Success:", value); // Only runs when operation succeeded
}

Why go-result?

  • Minimal: ~10 lines of code, zero dependencies
  • Type-safe: Leverages TypeScript's const assertions for precise types
  • Go-style: Familiar error handling pattern from Go
  • Explicit: Forces you to handle errors at the call site
  • Lightweight: Much simpler than alternatives like neverthrow or Effect.js

Comparison: go-result vs neverthrow vs Effect.js

Same functionality, drastically different verbosity:

Effect.js - Too Much Ceremony

import { Effect } from "effect";

// Define the operation
const divideEffect = (a: number, b: number) => (b === 0 ? Effect.fail("division by zero") : Effect.succeed(a / b));

// Use it (requires learning catchAll, tap, runSync...)
const result = divideEffect(10, 2).pipe(
  Effect.catchAll((error) => {
    console.error(error);
    return Effect.succeed(0);
  }),
  Effect.tap((value) => Effect.sync(() => console.log(value)))
);

Effect.runSync(result);
// ~15 lines, steep learning curve, runtime required

neverthrow - Better, But Still Verbose

import { Result, ok, err } from "neverthrow";

// Define the operation
const divide = (a: number, b: number): Result<number, string> => (b === 0 ? err("division by zero") : ok(a / b));

// Use it (requires learning isErr, isOk, error, value properties...)
const result = divide(10, 2);
if (result.isErr()) {
  console.error(result.error);
  return;
}
console.log(result.value);
// ~10 lines, custom API methods to remember

go-result - Simple and Direct

import { ok, err, type Result } from "go-result";

// Define the operation
const divide = (a: number, b: number): Result<number, string> => (b === 0 ? err("division by zero") : ok(a / b));

// Use it (just destructuring and if - patterns you already know)
const [value, error] = divide(10, 2);
if (error) return err(error);
console.log(value);
// ~7 lines, zero learning curve, zero runtime

Why go-result wins:

  • ✅ No custom methods to remember (isErr(), isOk(), .value, .error)
  • ✅ No pipes or effect systems to learn
  • ✅ No runtime overhead - just plain tuples
  • ✅ AI-friendly - LLMs rarely hallucinate with simple destructuring patterns
  • ✅ Familiar to anyone who knows Go or JavaScript destructuring

License

MIT


Attribution

The Go gopher was designed by Renee French. The gopher vector image is by Takuya Ueda, licensed under Creative Commons 3.0 Attributions. Source: golang-samples/gopher-vector