Skip to main content

Core Concepts

The Boxed approach takes root in typed functional paradigms. We know that these concepts can be overwhelming, especially with their jargon and mathematical concepts, and therefore want to make them more accessible.

As beautiful and powerful these concepts are, they come with a huge learning curve that we want to avoid. We also want your code to be simple to read, write and reason about without having to know the full theory behind.


If you have a strong opinion on what metaphor to use to describe monads, please stop reading this page immediately and visit the API reference.

Schrödinger's cat

When physicists discovered that particules do weird stuff, they decided that while we don't look at them, they're in a superposition of states.

Erwin Schrödinger didn't like that one bit and decided to show them how utterly stupid it was. For that, he created a thought experiment now called the Schrödinger's cat experiment, in which a cat is put into a box (roll credits) with a cat-killing device reacting to some quantum stuff. While we don't open the box, the cat is both alive and dead as the same time, when we open the box, we fix an outcome.

Schrödinger's cat experiment


We love cats and the boxes used in the following explanations will only contain JavaScript values.


The way we like to think of the data-structures we expose are that they're boxes (think of it as containers) that may or may not contain a value.

Here's a visual example using the Option type. The Option represents an optional value, it can have two possible states: either Some(value) or None().

Option of blue circle, it can be either a box containing a blue circle, which we call Some blue circle, or an empty box, which we call None

Option is a generic type, meaning you can define what type of value it holds: Option<User>, Option<string> (just like an array: Array<User>, Array<string>).

In your program flow, you don't know what's inside, as if the box was closed.

When you extract the value from the box, you have a few options:

// Let's assument we have `option` be of type `Option<number>`

// Returns the value if present or the fallback otherwise
const a = option.getOr(0);

// Explode the box
const b = option.match({
Some: (value) => value,
None: () => 0,

Data-manipulation basics

Most of the data-manipulation you'll do comes down to two function: map and flatMap.

Here's a visual explanation:

The map function transforms the value with a callback, the flatMap function returns an box itself

The map and flatMap functions allow you to transform data in a typesafe way:

const some = Option.Some(1);
// Option.Some<1>

const none = Option.None();
// Option.None

const doubledSome = => x * 2);
// Option.Some<2>

const doubledNone = => x * 2);
// Option.None -> Nothing to transform!

The flatMap lets you return another option, which can be useful for nested optional values:

type UserInfo = {
name: Option<string>;

type User = {
id: string;
info: Option<UserInfo>;

const name = user
.flatMap((user) => // Returns the Option<UserInfo>
.flatMap((info) => // Returns the Option<string>
.getOr("Anonymous user");

The main kind of boxes


Represents optional values:

  • Replaces undefined and null
  • Makes it possible to differentiate nested optionality (Some(None()) vs None())
  • Reduces the number of codepaths needed to read and transform such values

Result<Ok, Error>

Represents a computation that can either succeed or fail:

  • Replaces exceptions
  • Allows you to have a single codepath instead or "return or throw".
  • Makes it easy to aggregate all possible errors a stack can generate


Represents a value with an asynchronous lifecycle:

  • Eliminates impossibles cases in your state
  • Avoids inconsistent states induced by traditional modeling
  • Allows you to tie the lifecycle information with the value itself


Represents an asynchronous value:

  • Replaces promises
  • Supports cancellation
  • Delegates success/failure to the Result type
  • Exposes a map & flatMap API