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

safe-wrapper

v4.0.0

Published

a ts-util for safely wrapping synchronous and asynchronous functions to handle errors based on specified types.

Readme

safe-wrapper

npm version License Build Status npm downloads

safe-wrapper is a lightweight, typescript-first utility that simplifies error handling for both synchronous and asynchronous functions. inspired by the safe assignment operator proposal, this utility allows for graceful error management by wrapping functions in a way that enables error handling without the need for explicit try-catch blocks.

in modern javascript and typescript, dealing with functions that might throw errors (especially in asynchronous operations or third-party libraries) often leads to repetitive boilerplate. safe-wrapper offers a cleaner and a more functional approach by reducing boilerplate, enabling full typescript support for type inference, and allowing for flexible error handling by letting you filter specific error types, or transform them into custom formats.

Features

  • handles synchronous and asynchronous functions.
  • supports specifying error types to control which errors are caught and handled.
  • returns a consistent response in [error, result] format,
    • error: null if successful, else an error (or transformed object).
    • result: return value (sync) or resolved value (async) when successful, else null.
  • supports custom error transformation for advanced error handling.
  • written in typescript with comprehensive type definitions, enabling full type inference support.

Installation

npm install safe-wrapper

Usage

import safe from safe-wrapper to use it with any function. the types for error and result are automatically inferred.

the safe function takes a target function (synchronous or asynchronous) and returns a function which handles errors and returns a response in a consistent way. the function returns an array [error, result], where error is an instance of the specified error type or null if successful, and result is the result of the function when there is no error.

directly wrapping functions

we can directly wrap any function definition with safe.

import { safe } from 'safe-wrapper';

const safeSync = safe((args) => {
  throw new Error('sync error occurred');
});

const safeAsync = safe(async (args) => {
  throw new Error('async error occurred');
});

const [error, result] = await safeAsync(args);

wrapping existing functions

safe can be applied to pre-existing functions, including ones from third-party libraries.

import { safe } from 'safe-wrapper';

const sync = (args) => {
  throw new Error('sync error occurred');
}

const safeSync = safe(sync);
const [error, result] = safeSync(args);

handling specific error types

we can specify error types to catch, allowing other errors to throw.

import { safe } from 'safe-wrapper';

const safeAsync = safe(async (args) => {
  throw new TypeError('async type error occurred');
}, [TypeError]);

const [error, result] = await safeAsync(args);

handling multiple error types

we can specify multiple error types when wrapping a function, enabling safe to catch any of the specified errors.

import { safe } from 'safe-wrapper';

const sync = (args: boolean): string => {
  if (args) {
    throw new TypeError('sync type error occurred');
  } else {
    throw new RangeError('sync range error occurred');
  }
}

const safeSync = safe(sync, [TypeError, RangeError]);
const [error, result] = safeSync(args);

using synchronous custom error transformer

you can provide a custom error transformer function to modify how errors are handled:

import { safe } from 'safe-wrapper';

type TransformedError = { code: string, message: string, timestamp: Date };

const transformer = (error: Error): TransformedError => ({
  code: error.name,
  message: error.message,
  timestamp: new Date()
});

const safeWithTransform = safe(
  () => { throw new Error('custom sync error'); },
  [Error],
  transformer
);

const [error, result] = safeWithTransform();
// error will be of type TransformedError as: { code: 'Error', message: 'custom sync error', timestamp: Date }

using asynchronous custom error transformer

you can provide an asynchronous custom error transformer to modify how errors are handled.

import { safe } from 'safe-wrapper';

type AsyncTransformedError = { code: string, message: string, timestamp: Date };

const transformer = async (error: Error): Promise<AsyncTransformedError> => {
  await report(error);

  return {
    code: error.name,
    message: error.message,
    timestamp: new Date()
  }
}

const safeWithTransform = safe(
  async () => { throw new Error('custom async error'); },
  [Error],
  transformer
);

const [error, result] = await safeWithTransform();
// error will be of type AsyncTransformedError as: { code: 'Error', message: 'custom async error', timestamp: Date }

wrapping built-in functions

we can also wrap built-in functions, like JSON.parse, Object.keys, and more.

import { safe } from 'safe-wrapper';

const safeJsonParse = safe(JSON.parse);
const [error, result] = safeJsonParse('invalid_json');

const [error, result] = safe(Object.keys, [TypeError])(null);

API Reference

safe(action, types, transformer)

  • parameters
    • action (function): function to be wrapped. it can either be synchronous or asynchronous.
    • types (array, optional): an array of error types to catch. if no types are specified, all errors are caught. each element must be a valid error constructor.
    • transformer (function, optional): a function that takes an error object and returns a transformed version of it. if not provided, the original error is used.
  • returns [error, result]
    • error (error | null): the error object if error occurred, otherwise null. if an transformer is provided, this will be the transformed error.
    • result (result | null): the result of the action function if no error occurred, otherwise null.