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

oxidize

v1.0.6

Published

A Rust-inspired utility library for TypeScript and JavaScript

Readme

Oxidize

Yet another Rust-inspired TypeScript / JavaScript utility library.

This library was created to lower the cognitive load of writing a library which could throw errors from low-levels that needed to be propagated and handled at high-levels. Rather than using a series of try/catch blocks, I decided to translate some common utility structures from Rust to make it easier to keep track of which functions were generating errors further "up" in the program.

This library also focuses on trying to synchronize with normal TypeScript and JavaScript. Probably the most common example is the ability to wrap code blocks in Result.wrap() to create Results and the ability to use result.unwrap() to return a value or throw the error. Since the error stack is generated when an Error is created, the stack and message will be preserved and continue to trace back to the source where the error originated.

Installation and Use

Oxidize can be installed from NPM:

npm install [--global --save-dev --save] oxidize

For most use-cases, the default import should be sufficient:

const oxidize = require("oxidize");

For less common use-cases, though, you may want greater control over how your dependencies are written:

  • CommonJS: const oxidize = require("oxidize");
  • ES Modules: import { Ok, None } from "oxidize";

Features

Result

The Result type provides an error-handling structure that makes error-handling deliberate and explicit.

Error-handling is a common software engineering problem in any non-trivial project. JavaScript's built-in error-handling involves thrown exceptions and try...catch statements. This is a simple and (often) effective tool that has one major flaw:

const A = () => B();
const B = () => C();
const C = () => D();
const E = () => F();
const F = () => {
  throw new Error("Foo");
};

In a non-trivial system, where functions A and F may not be in the same file, it is unrealistic to expect the author of function A to know that they they will need to catch an error.

Result<T, F> is the type used for explicitly returning and propagating errors in a way that makes error-handling straightforward.

type Version = 1 | 2;

function parseVersion(header: number[]): Result<Version, string> {
  switch (header[0]) {
    case null:
      return Fail("invalid header length");
    case 1:
      return Ok(1);
    case 2:
      return Ok(2);
    default:
      return Fail("invalid version");
  }
}

const version = parseVersion([1, 2, 3, 4]);
version.match({
  Ok(v) {
    console.log(`Working with version: ${v}`);
  },
  Fail(f) {
    console.error(`Error parsing header: ${f}`);
  }
});

It's not always possible to do this, though. For example, if a dependency library provides a function that can throw, then being able to consume those thrown values as Results would result in some non-ergonomic code:

function throwEven(n: number) {
  if (n % 2 === 0) {
    throw new Error(`Even number thrown: ${n}`);
  }
  return n;
}

let result;
try {
  result = Some(throwEven(2));
} catch (e) {
  result = None();
}

In these cases, we can use Result.wrap to automatically collect those values with less syntactical cruft:

const result = Result.wrap(() => throwEven(2));

Pattern matching on Result is clear and straightforward for simple cases, but Result comes with some Rust-inspired convenience methods that make working with it more succinct.

The isOk and isErr methods do what they say:

let goodResult: Result<number, number> = Ok(10);
let badResult: Result<number, number> = Fail(10);

expect(goodResult.isOk() && !goodResult.isFail()).toBe(true);
expect(badResult.isFail() && !badResult.isOk()).toBe(true);

The map consumes the Result and produces another:

goodResult = goodResult.map(i => i + 1);
badResult = badResult.map(i => i - 1);

Use andThen to continue the computation:

let convertedResult: Result<bool, number> = goodResult.andThen(i =>
  Ok(i === 11)
);

Use orElse to handle the error:

let fixedResult: Result<number, number> = badResult.orElse(i => Ok(i + 20));

Extract the value with unwrap if the value is valid:

let finalResult: number = fixedResult.unwrap();

Option

Makes optional values explicit.

For function parameters in TypeScript, it is usually preferred to use the ? symbol or to use a default value to identify an optional parameter:

function double(n: number = 0) {
  return n * 2;
}

function toString(n?: string) {
  if (n) {
    return n;
  }
  return "";
}

Type Option represents an optional value, where every Option is either Some and contains a value, or None and does not. In TypeScript, this is usually represented as either T | null or val?: T; and in most cases, this is sufficient. However, sometimes it is syntactically unclear whether an undefined or null value represents a deliberate "missing" value or is caused by an upstream logic error. The Option class fills this void by making these choices explicit and enforcing them at runtime.

function divide(numerator: number, denominator: number): Option<number> {
  if (denominator === 0) {
    return None();
  } else {
    return Some(numerator / denominator);
  }
}

// The return value of the function is an `Option<number>`
const result = divide(2, 3);

if (result.isSome()) {
  console.log(`Result: ${result.unwrap()}`);
} else {
  console.log("Cannot divide by 0");
}

In the above case, the Option<number> value is taking the place of a recoverable error to prevent an operation could result in Infinity, or NaN. When passing the result of this function around, it is not always clear that you will need to account for the technically allowed but not necessarily desirable behavior of returning those special number values.

Using Option<T> makes those potential failures explicit, and allows you to correct the cause of bugs at their source without disrupting the code where those buggy values would be received.

The if/else pattern is common enough that there are some shorthand functions, as well:

let value = divide(2, 0).match({
  Some: x => x,
  None: () => 0
});

value = divide(2, 0).unwrapOr(0);

The Option.from<T>(val?: T | Option<T> | null) function simplifies the process of consuming normal JavaScript values and converts them into Option<T> instances by interpreting null and undefined values to be None<T>, and anything else to be Some<T>.

This function will also check if a value is already an Option and, if so, then it will return that Option instead. This approach could be overkill in trivial cases; but it does simplify the process of interacting with other Option values.

function double(number?: number): number {
  const maybeNumber = Option.from(number);
  return maybeNumber.unwrapOr(0) * 2;
}

expect(double()).toBe(0);
expect(double(1)).toBe(2);
expect(double(None())).toBe(0);
expect(double(Some(2))).toBe(4);