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

fp-result

v1.0.0

Published

A functional programming Result type for TypeScript

Readme

fp-result

A lightweight functional programming Result type for TypeScript. Provides a small, typed Ok / Err abstraction for handling success and failure without throwing.

Features

  • Strong TypeScript typings
  • Ok and Err variants
  • Safe accessors and combinators: map, fold, getOrDefault, getOrElse, getOrThrow
  • JSON-serializable representation
  • Built with TypeScript and distributed from dist/ with typings (dist/index.d.ts)

Install

npm install fp-result

Quick Usage

import { Result, ResultErr } from 'fp-result'

// Define a custom error that extends ResultErr and provides a `_tag`
class NotFoundError extends ResultErr {
  public override readonly _tag = 'NotFoundError'
  
  constructor(message = 'Resource not found') {
    super(message)
  }
}

// Create results
const ok = Result.ok(42)
const err = Result.err(new NotFoundError('Item 123 not found'))

// Inspect
if (ok.isOk) console.log(ok.value) // 42

console.log(err.isErr) // true
console.log(err.errOrNull()?.message) // 'Item 123 not found'

// Defaults / fallbacks
const value = err.getOrDefault(0) // 0
const computed = err.getOrElse(e => {
  console.error(e)

  return -1
})

// Transform / fold
const doubled = Result.ok(2).map(n => n * 2) // Ok(4)
const folded = err.fold(
  v => `ok: ${v}`,
  e => `err: ${e.message}`
)

// Throwing
// err.getOrThrow() // will throw the contained ResultErr subtype

Error validation with switch

Example showing two error subtypes that extend ResultErr and provide the discriminant _tag. Using a switch lets TypeScript narrow the error type for case-specific handling and enforces exhaustiveness.

import { Result, ResultErr } from 'fp-result'

class NotFoundError extends ResultErr {
  public override readonly _tag = 'NotFoundError'
  
  constructor(public readonly resource: string, message = 'Resource not found') {
    super(message)
  }
}

class ValidationError extends ResultErr {
  public override readonly _tag = 'ValidationError'
  
  constructor(public readonly field: string, message = 'Invalid value') {
    super(message)
  }
}

type OrderResult = Result<number, NotFoundError | ValidationError>

function getOrder(id: string): OrderResult {
  if (id === '1') return Result.ok(42)
  if (id === '2') return Result.err(new NotFoundError('order', `Order ${id} missing`))
  
  return Result.err(new ValidationError('id', 'Malformed id'))
}

const res = getOrder('3')
const message = res.fold(
  value => `Order id: ${value}`, // Ok handler
  err => {                       // Err handler
    switch (err._tag) {
      case 'NotFoundError':
        return `Not found: ${err.resource} — ${err.message}`
      case 'ValidationError':
        return `Validation error on \`${err.field}\`: ${err.message}`
    }
  }
)

console.log(message)

Make the switch exhaustiveness checked by TypeScript

To have TypeScript report non‑exhaustive switch statements when you use the discriminant _tag, disallow fallthrough in tsconfig.json (set "noFallthroughCasesInSwitch": true).

Example tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "noFallthroughCasesInSwitch": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

API (summary)

  • Result.ok<T>(value: T): Result<T, never>
  • Result.err<E extends ResultErr>(value: E): Result<never, E>
  • Instance:
    • isOk: boolean
    • isErr: boolean
    • value: T | E
    • getOrDefault(defaultValue: T): T
    • getOrElse(onErr: (err: E) => T): T
    • getOrNull(): T | null
    • errOrNull(): E | null
    • getOrThrow(): T
    • map<U>(fn: (value: T) => U): Result<U, E>
    • fold<R>(ifOk: (value: T) => R, ifErr: (error: E) => R): R
    • toJSON(): { value: T | E, isOk: boolean, isErr: boolean }
    • toString(): string