Option<Value>
The Option
type can be used as a replacement for null
and undefined
when manipulating optional data. Contrary to null
and undefined
, an option is kind of like a box, that contains a value or not.
It can be useful to distinguish values between each other: you can represent Some(None)
with options, whereas undefined
or null
replace the value they intend to make optional.
An option can have two possible states:
Some(value)
None
Create an Option value
To create an option, use the Some
and None
constructors:
import { Option } from "@swan-io/boxed";
const aName = Option.Some("John");
const bName = Option.None();
// You can enforce the type using a type parameter
Option.Some<string>("John");
Option.None<string>();
You get interop with null
and undefined
:
// `value` being `null` or `undefined` makes a `None`
const a = Option.fromNullable(value);
// `value` being `null` makes a `None`
const b = Option.fromNull(value);
// `value` being `undefined` makes a `None`
const c = Option.fromUndefined(value);
Methods
The option type provides a few manipulation functions:
.map(f)
Option<A>.map<B>(f: (value: A) => B): Option<B>
If the option is Some(value)
returns Some(f(value))
, otherwise returns None
.
Option.Some(2).map((x) => x * 2);
// Option.Some<4>
Option.None().map((x) => x * 2);
// Option.None
.flatMap(f)
Option<A>.flatMap<B>(f: (value: A) => Option<B>): Option<B>
If the option is Some(value)
returns f(value)
, otherwise returns None
.
Option.Some(3).flatMap((x) => (x > 2 ? Option.None() : Option.Some(2)));
// Option.None
Option.Some(1).flatMap((x) => (x > 2 ? Option.None() : Option.Some(2)));
// Option.Some<2>
option.flatMap((value) => value.optionalProperty);
// Option<optionalProperty>
.getWithDefault(defaultValue)
Option<A>.getWithDefault(defaultValue: A): A
If the option is Some(value)
returns value
, otherwise returns defaultValue
.
Option.Some(2).getWithDefault(1);
// 2
Option.None().getWithDefault(1);
// 1
.get()
Option<A>.get(): A
Returns the value contained in Some(value)
. Only usable within a isSome()
check.
const value = option.get();
// does not compile
if (option.isSome()) {
const value = option.get();
// value
}
.isSome()
Option<A>.isSome(): boolean
Type guard. Checks if the option is Some(value)
Option.Some(2).isSome();
// true
Option.None().isSome();
// false
if (option.isSome()) {
const value = option.get();
}
.isNone()
Option<A>.isNone(): boolean
Type guard. Checks if the option is None
Option.Some(2).isNone();
// false
Option.None().isNone();
// true
.toNull()
Option<A>.toNull(): A | null
Returns null
if the option is None
, returns the value otherwise
Option.Some(2).toNull();
// 2
Option.None().toNull();
// null
.toUndefined()
Option<A>.toUndefined(): A | undefined
Returns undefined
if the option is None
, returns the value otherwise
Option.Some(2).toUndefined();
// 2
Option.None().toUndefined();
// undefined
.toResult(errorWhenNone)
Option<A>.toResult<E>(valueWhenNone: E): Result<A, E>
Returns Ok
if the option is Some
, returns Error
otherwise
const a = Option.Some(1).toResult("NotFound");
// Ok<1>
const b = Option.None().toResult("NotFound");
// Error<"NotFound">
.match()
Option<A>.match<B>(config: {
Some: (value: A) => B;
None: () => B;
}): B
Match the option state
const valueToDisplay = option.match({
Some: (value) => value,
None: () => "No value",
});
// value | "No value"
.tap(func)
Option<A>.tap(func: (option: Option<A>) => unknown): Option<A>
Executes func
with option
, and returns option
. Useful for logging and debugging.
option.tap(console.log).map((x) => x * 2);
Statics
Option.all(options)
all(options: Array<Option<A>>): Option<Array<A>>
Turns an "array of options of value" into a "option of array of value".
Option.all([Option.Some(1), Option.Some(2), Option.Some(3)]);
// Some([1, 2, 3])
Option.all([Option.None(), Option.Some(2), Option.Some(3)]);
// None
Option.allFromDict(options)
allFromDict(options: Dict<Option<A>>): Option<Dict<A>>
Turns a "dict of options of value" into a "option of dict of value".
Option.allFromDict({ a: Option.Some(1), b: Option.Some(2), c: Option.Some(3) });
// Some({a: 1, b: 2, c: 3})
Option.allFromDict({ a: Option.None(), b: Option.Some(2), c: Option.Some(3) });
// None
TS Pattern interop
import { match, P } from "ts-pattern";
import { Option } from "@swan-io/boxed";
match(myOption)
.with(Option.pattern.Some(P.select()), (value) => console.log(value))
.with(Option.pattern.None, () => "No value")
.exhaustive();
Cheatsheet
Method | Input | Function input | Function output | Returned value |
---|---|---|---|---|
map | Some(x) | x | y | Some(y) |
map | None() | not provided | not executed | None() |
flatMap | Some(x) | x | Some(y) | Some(y) |
flatMap | Some(x) | x | None() | None() |
flatMap | None() | not provided | not executed | None() |