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

@asleepace/try

v0.2.1

Published

TypeScript utilities for exception handling and errors-as-values.

Readme

Try

try-catch-cover

Type-safe error handling primitives for modern JavaScript & TypeScript projects.

Installation

Using npm:

npm install @asleepace/try

Using Yarn:

yarn add @asleepace/try

Using Bun:

bun add @asleepace/try

Quick Start

The goal of this package is to provide concise, type-safe and easy to use tools for handling exceptions.

import { Try } from '@asleepace/try'

const [url, error] = Try.catch(() => new URL(userInput))

if (error) return console.warn(error.message)

const [response, networkError] = await Try.catch(() => fetch(url))
const [jsonData, parsingError] = await Try.catch(() => response!.json())

if (parsingError) return console.warn(parsingError.message)

return jsonData.userName

Result Type

The Try.catch(fn) utility returns a special result type Res which is a class that extends a result tuple. The Res class provides some helpful utilities for handling results:

const result = await Try.catch(() => response.json())

// includes powerful type-guards
if (result.isErr()) return console.warn(result.error.message)

// and convenience methods
const json = result.unwrap()

// supports array destructuring
const [user, error] = await Try.catch(async () => {
  const profileUrl = new URL(json.user!.profile)
  return fetch(profileUrl).then((res) => res.json())
})

if (!error) {
  console.log(`Hello, ${user.name}!`)
} else {
  console.warn(error.message)
}

The can be used in conjunction with the array destructuring syntax, which can help if you are only interested in the value or error.

const result = await Try.catch(() =>
  fetch('https://api.users.com/me')
    .then((res) => res.json())
    .then((usr) => usr as User)
)

console.log(result.value) // User  | undefined
console.log(result.error) // Error | undefined

// automatically narrows the type for you!

if (result.isOk()) {
  const user = result.value // User!
} else {
  const fail = result.error // Error!
}

// in some cases you may just want the value or to throw again:

const user = result.unwrap() // User | never

// or you may want the value or a fallback:

const user = result.unwrapOr(cachedUser) // User

API

Try.catch<T>(fn: () => Promise<T>): Promise<[T, undefined] | [undefined, Error]>

Executes a function and returns a tuple containing either:

  • [value, undefined] if the function executes successfully
  • [undefined, error] if the function throws an error

Works with both synchronous and asynchronous functions, automatically returning a Promise for async operations.

Shorthand

This package also exports a shorthand utility called vet which stands for value / error tuple and provides a more concise way to interact with this api.

// Add more examples of the VET shorthand
import { vet } from '@asleepace/try'

// Simple usage
const [value] = vet(() => JSON.parse(data))

// Only get the error
const [, error] = vet(() => JSON.parse(data))

// With TypeScript generics for better type inference
const [user] = vet<User>(() => getUserFromAPI())

Benefits

  • No Try/Catch Blocks: Clean, readable code without nested try/catch structures
  • Type Safety: Full TypeScript support with proper type inference
  • Consistent Pattern: Uniform error handling for both sync and async code
  • Zero Dependencies: Lightweight and dependency-free
  • Isomorphic: Works in both browser and Node.js environments
  • Powerful Results: Type safe, tested and versatile result class

Testing

This package includes a comprehensive test suite. To run the tests:

# Clone the repository
git clone https://github.com/asleepace/try.git
cd try

# Install dependencies
bun install

# Build project & generate types
bun run build

# Run tests
bun test

Examples

Making Network Requests

// handle synchronous operations which can throw with ease...
const encoded = Try.catch(() => JSON.stringify(userInput))

if (!encoded.ok) return encoded.error

const [response, networkError] = await Try.catch(() =>
  fetch('https://api.com/create', {
    method: 'POST',
    body: encoded.value,
  })
)

if (networkError) return networkError

const [user, jsonError] = await Try.catch(response.json)

if (jsonError) return jsonError

return user

Error Handling in a React Component

import React, { useEffect, useState } from 'react'
import { Try } from '@asleepace/try'

function UserProfile({ userId }) {
  const [user, setUser] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    async function loadUser() {
      setLoading(true)

      const [userData, fetchError] = await Try.catch(async () => {
        const response = await fetch(`/api/users/${userId}`)
        if (!response.ok) throw new Error(`HTTP error ${response.status}`)
        return response.json()
      })

      setUser(userData)
      setError(fetchError)
      setLoading(false)
    }

    loadUser()
  }, [userId])

  if (loading) return <div>Loading...</div>
  if (error) return <div>Error: {error.message}</div>

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  )
}

Chaining Operations

import { Try } from '@asleepace/try'

async function processData(rawData): object | undefined {
  // Step 1: Parse the data
  const [parsed, parseError] = Try.catch(() => JSON.parse(rawData))
  if (parseError) return console.warn(parseError.message)

  // Step 2: Transform the data
  const [transformed, transformError] = Try.catch(() => {
    return parsed.items.map((item) => ({
      id: item.id,
      name: item.name.toUpperCase(),
      value: item.value * 2,
    }))
  })
  if (transformError) return console.warn(transformError.message)

  // Step 3: Save the data
  const saveResult = await Try.catch(async () => {
    const response = await fetch('/api/save', {
      body: JSON.stringify(transformed),
      method: 'POST',
    })
    return response.json()
  })

  if (saveResult.isErr()) return console.warn(saveResult.error)
  return saveResult.unwrap()
}

Specification

Overview

The Try.catch utility provides a type-safe way to handle errors in both synchronous and asynchronous functions, returning a result tuple that contains either a value or an error, but never both.

Return Values

  • Try.catch always returns either a ResultOk<T> or ResultError type, which extends the tuple types [T, undefined] or [undefined, Error] respectively.
  • The returned object is guaranteed to have exactly two elements, with either index 0 or index 1 being undefined.
  • If the function completes successfully, index 0 will contain the return value and index 1 will be undefined.
  • If the function throws an error, index 0 will be undefined and index 1 will contain the error.

Error Handling

  • If a non-Error value is thrown (such as a string, number, or object), it will be automatically converted to an instance of the built-in Error class.
  • Thrown values that aren't already errors will first be coerced to strings and then used to construct a new Error instance.
  • If the function returns an Error object as its value (not thrown), it will be treated as a successful result with the Error as the value at index 0, not as an error case.

Properties and Methods

The returned result object includes several convenience properties and methods:

  • .value: Returns the value at index 0 (the success value) or undefined if an error occurred.
  • .error: Returns the error at index 1 or undefined if the operation was successful.
  • .ok: A boolean property that is true when .error === undefined and false otherwise.
  • .unwrap(): Returns the value if present, or throws the captured error if no value is present.
  • .unwrapOr(fallback): Returns the value if present, or the provided fallback value if no value is present.
  • .toString(): Returns a string representation of the result, displaying either the successful value or the error message.

Type Safety

  • The returned result type correctly narrows in type-guard contexts:
    • When checking if (result.ok), TypeScript will narrow the type to ResultOk<T>.
    • When checking if (!result.ok), TypeScript will narrow the type to ResultError.
  • In ResultOk<T> contexts, result.value is typed as T and result.error is typed as undefined.
  • In ResultError contexts, result.value is typed as undefined and result.error is typed as Error.

Async Support

  • Try.catch supports both synchronous and asynchronous functions.
  • When passed a function that returns a Promise, Try.catch returns a Promise that resolves to a result tuple.
  • Rejected promises are captured and converted to error results, following the same rules as thrown errors.

Instanceof Support

  • The returned result object is an instance of TryResultClass, enabling instanceof checks.
  • This allows for easier type checking and integration with existing code patterns.

Changelog

0.2.1

  • add Res.ok(value) and Res.err(error) initializers
  • add isOk() and isErr() type guards to result
  • move all code into src/index.ts
  • remove junks files and reduce package size
  • remove internal Try.#handler method
  • simplify Try.catch logic
  • simplify types

0.2.0

  • add vet(fn) shorthand
  • add convenience methods
  • Update Result class
  • Update test suite

0.14.0

  • Update README.md
  • Update Try.catch functionality

0.13.0

  • Initial release

License

MIT