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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@iwburns/tupperware

v2.0.0

Published

A package containing Optional and Result types

Downloads

50

Readme

tupperware

Build Status Coverage Status npm Documentation GitHub license

A library for safely and consistently dealing with complex values in Javascript and Typescript.

Overview

This library provides two types for dealing with optional / conditional values:

  • Optional - A type representing an optional value.
  • Result - A type representing the result of some fallible computation.

Optional

A value of this type is either a Some or a None. Some-values contain a value internally while None-values represent the absence of a given value. This is useful when you have a value that may or may not exist. Where you might otherwise use null or undefined to represent the absense of a value, you can use a None value instead.

Consider getting a property of an object that may or may not exist:

Normally you might do this:

const data = getSomeData(); // we may not know what data looks like here

let c = 0; // make sure you default it

if (typeof data.c !== 'undefined' && data.c !== null) { // make sure data.c exists
  c = data.c;
}

doSomething(c);  // now we can use c

Instead you could do this:

const data = getSomeData();

let optC = getProperty(data, 'c');  // returns an Optional
let c = optC.unwrapOr(0);           // we can use unwrapOr to safely get the value or
                                    // a default value if c wasn't present on data

doSomething(c);

Or if we want to avoid doing anything when c doesn't exist:

const data = getSomeData();

let optC = getProperty(data, 'c');  // returns an Optional

optC.forEach(doSomething);          // forEach will call doSomething with optC's internal
                                    // value if it exists, otherwise nothing happens

The key to this being useful is that both Some and None are wrapped in the same API. This means you can call forEach and unwrapOr (and a bunch of other methods) on the return value regardless of whether it's a Some or a None.

Note: This library doesn't provide a getProperty() function but one could imagine it looking something like:

function getProperty(obj, propName) {
  if (typeof obj[propName] !== 'undefined' && obj[propName] !== null) {
    return Optional.some(obj[propName]); // return a `Some`-value containing the value internally
  }
  return Optional.none(); // otherwise return a `None`-value
}

Result

A value of this type is either an Ok or an Err. Both of these contain an internal value, but they each convey a different meaning. Ok is used to represent an operation that succeeded and returned some kind of successful result. Err is used to represent an operation that failed and returned some kind of error.

Consider parsing a number out of a string:

Normally you might do this:

const aNumber = getANumber(); // we may not know if this is a valid number

const result = parseInt(aNumber, 10); // do our parsing

let parsed = 0; // default it

if (!Number.isNaN(result)) { // if it didn't fail, hold on to the parsed value
  parsed = result;
}

doSomething(parsed); // now we can use it

Instead you could do this:

const aNumber = getANumber(); // we may not know if this is a valid number

const result = safeParseInt(aNumber, 10); // returns a Result

const parsed = result.unwrapOr(0);  // we can use unwrapOr to safely get the value or
                                    // a default value if the result was an Err-value

doSomething(parsed); // now we can use it

Or if you want to handle both cases explicitly:

const aNumber = getANumber(); // we may not know if this is a valid number

const result = safeParseInt(aNumber, 10); // returns a Result

// result.match will call the given ok function if the result is an Ok-value
// and it will call the given err function if it is an Err-value
result.match({
  ok: value => { doSomething(value); },    // pass the parsed value to `doSomething`
  err: error => { console.error(error); }, // or do whatever you need to do with the error
});

Again, the key here is that both Ok and Err values are wrapped in the same API. This means you can treat them both the same and just describe how you want them to behave instead of writing all of the boiler-plate logic every time you deal with them.

Note: This library doesn't provide a safeParseInt() function but it might look something like this if it were provided:

function safeParseInt(num, radix) {
  let parsed = parseInt(num, radix);
  if (Number.isNaN(parsed)) {
    // return an Err-value with a meaningful error message
    return Result.Err(`Could not parse the value: ${num} as an integer with radix: ${radix}`);
  }
  // otherwise return an Ok-value with the parsed value inside
  return Result.Ok(parsed);
}

Contributors