Skip to main content

Actions Status GitHub release (latest by date) GitHub deno doc

Resulty

This library provides Rust-like Result and Option objects for Deno. It makes error handling easier by reducing side effects and removes the need for mixed return types.

Instead of throwing exceptions everywhere you can easily bubble up errors by returning a Result type which is either an instance of Ok or Err. And the Option objects allow you to return a standard type where the result of a method maybe something or nothing.

Installation / Setup

To add Resulty to your project import the ok(), err(), some() and none() methods along with the Result<T> and Opt<T> types from https://deno.land/x/resulty@0.4.0/mod.ts.

import { 
  ok, 
  err, 
  some, 
  none, 
  Result, 
  Opt,
  Panic,
} from "https://deno.land/x/resulty@0.4.0/mod.ts"

Usage

The core functionality of the this library is contained in the ok(), err(), some() and none() methods. The ok() and err() methods return an instance of Result<T>, and the some() and none() methods return an instance of Opt<T>.

Both Result<T> and Opt<T> are wrappers for other types and objects. And you can access these contained types and objects via the unwrap() method.

import { Result, ok } from "https://deno.land/x/resulty@0.4.0/mod.ts";

const isOk: Result<string> = ok("Hello");

console.log(isOk.unwrap());
// Hello

Unwrap vs Unwrap Err and Unwrap None

Both Result and Option objects make an unwrap() method available which will return what is contained within the Result or Option object.

If the unwrap() method is called on an Err or None object it will Panic. If you need to retrieve what is contained in the Err object use the method unwrapErr().

An instance of None will not contain anything, but in certain instances you may wish to unwrap a None without panicking, you can do this by calling unwrapNone().

Result

Result objects can be generated by either the ok() or err() methods. The former represents a successful outcome the latter a failure.

Available Result<T> methods:

  • unwrap(): T | void;
  • unwrapErr(): T | void;
  • expect(message: string): T | void;
  • expectErr(message: string): T | void;
  • isOk(): boolean;
  • isErr(): boolean;

In this example the code returns a Result<string>. As you can see both the ok() and err() methods receive a string.

import { Result, ok, err } from "https://deno.land/x/resulty@0.4.0/mod.ts";

const isSandra = function (name: string): Result<string> {
  if (name === "Sandra") {
    return ok("Is Sandra");
  }
  return err("Is not Sandra");
};
  
const geoff = isSandra("Geoff");
console.log(geoff.unwrapErr());
// "Is not Sandra"

const sandra = isSandra("Sandra");

console.log(sandra.unwrap()); 
// "Is Sandra"

A more advanced use case may involve a situation where the ok() method receives a number and the err() method receives a string. In this scenario you can reference a union type in the Result<number | string> return type.

import { Result, ok, err } from "https://deno.land/x/resulty@0.4.0/mod.ts";

const findNumber = function (toFind: number): Result<number | string> {
  const numbers = [1, 4, 6, 7, 21, 33];
  
  if (numbers.includes(toFind)) {
    return ok(toFind);
  }
  return err(`Number: ${toFind} could not be found.`);
};

const found = findNumber(6);
console.log(found.unwrap());
// 6

const notFound = findNumber(9);
console.log(notFound.unwrapErr())
// Number: 9 could not be found.

Option

Option objects can be generated via the some() or none() methods.

Available Opt<T> methods:

  • unwrap(): T | void;
  • unwrapNone(): T | void;
  • expect(message: string): T | void;
  • expectNone(message: string): T | void;
  • isSome(): boolean;
  • isNone(): boolean;

Options are useful in scenarios where a system failure hasn’t occurred but either something or nothing can be returned. For instance when looking for a record in a data store of some kind.

import { Opt, some, none } from "https://deno.land/x/resulty@0.4.0/mod.ts";

let findRecord = function (id: number): Opt<string> {
  let records = [{id: 1, value: "Hello"}, {id: 13, value: "World"}];
  
  records = records.filter((item) => {
    return item.id === id;
  });

  if (records.length === 1) {
    return some(records[0].value);
  }

  return none();
};

const found = findRecord(13);
console.log(found.unwrap());
// "World"

const notFound = findRecord(2);
console.log(notFound.unwrapNone());
// null