Option
Type Option represents an optional value:
every Option is either Some and contains
a value, or None, and does not. Option
types are very common, as they have a number of uses:
- Initial values
- Return value for otherwise reporting simple errors, where None is returned on error
- Optional object fields
- Optional function arguments
- Swapping things out of difficult situations
Variants
Constructors
none()- createsNonevariant.some<T>(value: T)- createsSome<T>variant.
Methods
and
and<U>(x: Option<U>): Option<U>
Takes another Option and returns None if this options is None, otherwise
returns provided option.
const x = some(2);
const y = none<number>();
expect(x.and(some(3))).toStrictEqual(some(3));
expect(x.and(none())).toStrictEqual(none());
expect(y.and(some(3))).toStrictEqual(none());
expect(y.and(none())).toStrictEqual(none());
andThen
andThen<U>(f: (x: T) => Option<U>): Option<U>
Takes a predicate function f that is called with current Option if it's Some,
otherwise returns None without calling the predicate.
const x = some(2);
const y = none<number>();
expect(x.andThen(n => some(n * 2))).toStrictEqual(some(4));
expect(x.andThen(_ => { throw new Error() })).toStrictEqual(none());
expect(x.andThen(_ => none())).toStrictEqual(none());
expect(y.andThen(n => some(n * 2))).toStrictEqual(none());
clone
clone<U>(this: Option<Cloneable<U>>): Option<U>
Returns a clone of the Option.
Only available on Options with Cloneable values.
class CloneableClass implements Clone<CloneableClass> {
constructor(public a: number) {}
clone(this: Clone<CloneableClass>): CloneableClass;
clone(this: CloneableClass): CloneableClass;
clone(): CloneableClass {
return new CloneableClass(this.a);
}
}
const cloneable = new CloneableClass(1);
const x = some(1);
const y = some(cloneable);
expect(x.clone()).toStrictEqual(some(1));
expect(x.clone()).not.toBe(x); // Different reference
expect(x.clone().unwrap()).toBe(1);
expect(y.clone()).toStrictEqual(cloneable);
expect(y.clone()).not.toBe(cloneable);
combine
combine<U extends Option<unknown>[]>(...opts: U): Option<[T, ...SomeValues<U>]>
Combines this Option with other Option instances into a single
Option containing a tuple of values.
The combine method takes an arbitrary number of Option instances,
all sharing the same error-free structure. If all Option instances
(including this one) are Some, it returns an Option with a tuple of
their values in the order provided. If any Option is None, it returns
None. The resulting tuple includes the value of this Option as the first
element, followed by the values from the provided Option instances.
const a = some(Promise.resolve(1));
const b = some("hi");
const c = none<Date>();
const d = a.combine(b, c); // Option<[Promise<number>, string, Date]>
copy
Returns a shallow copy of the Option.
const value = { a: 1 };
const x = some(value);
const y = none<{ a: number }>();
expect(x.copy()).toStrictEqual(some({ a: 1 }));
expect(x.copy()).not.toBe(x); // Different option reference
expect(x.copy().unwrap()).toBe(value); // Same value reference
expect(y.copy()).toStrictEqual(none());
expect
expect(this: SettledOption<T>, msg?: string): T
Returns the value if Some, or throws an OptionError
with msg (or a default message) if None.
Only available on Options that are Settled.
This method throws if called on Option that is None.
const x = some(42);
const y = none<number>();
expect(x.expect("Missing value")).toBe(42);
expect(() => y.expect("Missing value")).toThrow("Missing value");
expect(() => y.expect()).toThrow("`expect`: called on `None`");
filter
filter(f: (x: T) => boolean): Option<T>
Returns the option if Some and f returns true, otherwise returns None.
If f throws, None is returned.
const x = some(2);
const y = none<number>();
expect(x.filter((n) => n > 0)).toStrictEqual(some(2));
expect(x.filter((n) => n < 0)).toStrictEqual(none());
expect(x.filter((_) => { throw new Error(); })).toStrictEqual(none());
expect(y.filter((n) => n > 0)).toStrictEqual(none());
flatten
flatten<U>(this: Option<Option<U>>): Option<U>
Flattens an Option of an Option into a single Option.
Only available on Options that hold another Option.
const x: Option<Option<Option<number>>> = some(some(some(6)));
const y: Option<Option<number>> = x.flatten();
const z = none<Option<Option<number>>>();
expect(x.flatten()).toStrictEqual(some(some(6)));
expect(y.flatten()).toStrictEqual(some(6));
expect(z.flatten()).toStrictEqual(none());
getOrInsert
getOrInsert(this: SettledOption<T>, x: T): T
Returns the contained value if Some, or inserts and returns x if None.
See also insert method, which updates the value even if the option
already contains Some.
- Only available on
Options that areSettled. - This method mutates the
Option.
const x = some(2);
const y = none<number>();
expect(x.getOrInsert(5)).toBe(2);
expect(y.getOrInsert(5)).toBe(5);
expect(y).toStrictEqual(some(5)); // y is mutated
getOrInsertWith
getOrInsertWith(this: SettledOption<T>, f: () => T): T
Returns the value if Some, or inserts and returns the result of f if None.
- Only available on
Options that areSettled. - Mutates this option to
Somewithf’s result ifNone. Iffthrows, the option remains unchanged.
Throws OptionError if f throws.
const x = some(2);
const y = none<number>();
const z = none<number>();
expect(x.getOrInsertWith(() => 5)).toBe(2);
expect(y.getOrInsertWith(() => 5)).toBe(5);
expect(y).toStrictEqual(some(5)); // Mutated
expect(() => z.getOrInsertWith(() => { throw new Error(); }))
.toThrow("`getOrInsertWith`: callback `f` threw an exception");
expect(z).toStrictEqual(none()); // Unchanged
insert
insert(this: SettledOption<T>, x: T): T
Inserts x into the option and returns it, overwriting any existing value.
See also getOrInsert method, which doesn’t update the value if
the option already contains Some.
- Only available on
Options that areSettled. - This method mutates the
Option.
const x = some(2);
const y = none<number>();
expect(x.insert(5)).toBe(5);
expect(x).toStrictEqual(some(5));
expect(y.insert(5)).toBe(5);
expect(y).toStrictEqual(some(5));
inspect
inspect(f: (x: T) => unknown): Option<T>
Calls f with the value if Some, then returns a copy of this option.
- Returns a new
Optioninstance, not the original reference. - If
fthrows or returns aPromisethat rejects, the error is ignored.
const x = some(2);
const y = none<number>();
let sideEffect = 0;
expect(x.inspect((n) => (sideEffect = n))).toStrictEqual(some(2));
expect(x.inspect((_) => { throw new Error(); })).toStrictEqual(some(2));
expect(sideEffect).toBe(2);
expect(y.inspect((n) => (sideEffect = n))).toStrictEqual(none());
expect(sideEffect).toBe(2); // Unchanged
isNone
Returns true if the option is None.
const x = some(2);
const y = none<number>();
expect(x.isNone()).toBe(false);
expect(y.isNone()).toBe(true);
isNoneOr
isNoneOr(f: (x: T) => boolean): boolean
Returns true if the option is None or if f returns true for the contained value.
If f throws, false is returned.
const x = some(2);
const y = none<number>();
expect(x.isNoneOr((n) => n > 0)).toBe(true);
expect(x.isNoneOr((_) => { throw new Error(); })).toBe(false);
expect(x.isNoneOr((n) => n < 0)).toBe(false);
expect(y.isNoneOr((n) => n > 0)).toBe(true);
isSome
Returns true if the option is Some.
const x = some(2);
const y = none<number>();
expect(x.isSome()).toBe(true);
expect(y.isSome()).toBe(false);
isSomeAnd
isSomeAnd(f: (x: T) => boolean): this is Some<T> & boolean
Returns true if the option is Some and f returns true for the contained value.
If f throws, false is returned.
const x = some(2);
const y = none<number>();
expect(x.isSomeAnd((n) => n > 0)).toBe(true);
expect(x.isSomeAnd((_) => { throw new Error(); })).toBe(false);
expect(x.isSomeAnd((n) => n < 0)).toBe(false);
expect(y.isSomeAnd((n) => n > 0)).toBe(false);
iter
iter(): IterableIterator<T, T, void>
Returns an iterator over this option’s value, yielding it if Some or nothing if None.
- Yields exactly one item for
Some, or zero items forNone. - Compatible with
for...ofloops and spread operators.
const x = some(42);
const y = none<number>();
const iterX = x.iter();
expect(iterX.next()).toEqual({ value: 42, done: false });
expect(iterX.next()).toEqual({ done: true });
const iterY = y.iter();
expect(iterY.next()).toEqual({ done: true });
expect([...x.iter()]).toEqual([42]);
expect([...y.iter()]).toEqual([]);
map
map<U>(f: (x: T) => Awaited<U>): Option<U>
Maps the contained value with f if Some, returning a new Option;
otherwise, returns None.
If f throws, None is returned.
const x = some(2);
const y = none<number>();
expect(x.map((n) => n * 2)).toStrictEqual(some(4));
expect(x.map((_) => { throw new Error(); })).toStrictEqual(none());
expect(y.map((n) => n * 2)).toStrictEqual(none());
mapAll
mapAll<U>(f: (x: Option<T>) => Option<U>): Option<U>mapAll<U>(f: (x: Option<T>) => Promise<Option<U>>): PendingOption<Awaited<U>>
Maps this option by applying a callback to its full state, executing the callback for both Some
and None, returning a new Option or a PendingOption, depending on
what kind of predicate function was provided (see method overloads for more details).
Unlike andThen, which only invokes the callback for Some, this method always
calls f, passing the entire Option as its argument.
If f throws or returns a Promise that rejects, the error is silently ignored and None
(or a PendingOption resolves to None) is returned.
const someOpt = some(42);
const noneOpt = none<number>();
const undefOpt = some(undefined);
expect(someOpt.mapAll((opt) => some(opt.unwrapOr(0) + 1))).toStrictEqual(some(43));
expect(noneOpt.mapAll((opt) => some(opt.unwrapOr(0) + 1))).toStrictEqual(some(1));
expect(undefOpt.mapAll((opt) => some(opt.isSome() ? "some" : "none"))).toStrictEqual(some("some"));
const mappedSome = someOpt.mapAll((opt) => Promise.resolve(some(opt.unwrapOr(0))));
expect(isPendingOption(mappedSome)).toBe(true);
expect(await mappedSome).toStrictEqual(some(42));
const mappedNone = noneOpt.mapAll((opt) => Promise.resolve(some(opt.unwrapOr(0) + 1)));
expect(isPendingOption(mappedNone)).toBe(true);
expect(await mappedNone).toStrictEqual(some(1));
mapOr
mapOr<U>(this: SettledOption<T>, def: Awaited<U>, f: (x: T) => Awaited<U>): U
Returns f applied to the value if Some, otherwise returns def.
- Only available on
Options that areSettled. fhas to return a synchronous (Awaited) value.- If
fthrows, returnsdef.
const x = some(2);
const y = none<number>();
expect(x.mapOr(0, (n) => n * 2)).toBe(4);
expect(x.mapOr(0, (_) => { throw new Error(); })).toBe(0);
expect(y.mapOr(0, (n) => n * 2)).toBe(0);
mapOrElse
mapOrElse<U>(this: SettledOption<T>, mkDef: () => Awaited<U>, f: (x: T) => Awaited<U>): U
Returns f applied to the contained value if Some, otherwise returns the result of mkDef.
- Only available on
Options that areSettled. - If
fthrows, the error is silently ignored and result ofmkDefis returned.
Throws OptionError if mkDef is called and throws an exception.
Original error will be set as OptionError.reason.
const x = some(2);
const y = none<number>();
expect(x.mapOrElse(() => 0, n => n * 2)).toBe(4);
expect(x.mapOrElse(() => 1, _ => { throw new Error() })).toBe(1);
expect(() => x.mapOrElse(() => { throw new Error() }, _ => { throw new Error() })).toThrow(OptionError);
expect(y.mapOrElse(() => 0, n => n * 2)).toBe(0);
match
match<U, F = U>(this: SettledOption<T>, f: (x: T) => Awaited<U>, g: () => Awaited<F>): U | F
Matches the option, returning f applied to the value if Some, or g if None.
- Only available on
Options that areSettled. - If
forgreturns aPromisethat rejects, the caller is responsible for handling the rejection.
Throws OptionError if f or g throws an exception.
Original error will be set as OptionError.reason.
const x = some(2);
const y = none<number>();
expect(x.match(n => n * 2, () => 0)).toBe(4);
expect(() => x.match(_ => { throw new Error() }, () => 0)).toThrow(OptionError);
expect(y.match(n => n * 2, () => 0)).toBe(0);
expect(() => y.match(n => n * 2, () => { throw new Error() })).toThrow(OptionError);
okOr
okOr<E>(y: Awaited<E>): Result<T, E>
Converts to a Result, using y as the error value if
this option is None. Some(v) is mapped to Ok(v) and None to Err(y).
const x = some(2);
const y = none<number>();
expect(x.okOr("error")).toStrictEqual(ok(2));
expect(y.okOr("error")).toStrictEqual(err("error"));
okOrElse
okOrElse<E>(mkErr: () => Awaited<E>): Result<T, E>
Converts to a Result, using the result of mkErr as the error value if None.
Some(v) is mapped to Ok(v) and None to Err(mkErr()).
const x = some(2);
const y = none<number>();
expect(x.okOrElse(() => "error")).toStrictEqual(ok(2));
expect(y.okOrElse(() => "error")).toStrictEqual(err("error"));
or
Returns the current option if it is Some, otherwise returns x.
const x = some(2);
const y = none<number>();
expect(x.or(some(3))).toStrictEqual(some(2));
expect(x.or(none())).toStrictEqual(some(2));
expect(y.or(some(3))).toStrictEqual(some(3));
expect(y.or(none())).toStrictEqual(none());
orElse
orElse(f: () => Option<T>): Option<T>
Returns the current option if Some, otherwise returns the result of f.
If f throws, None is returned.
const x = some(2);
const y = none<number>();
expect(x.orElse(() => some(3))).toStrictEqual(some(2));
expect(y.orElse(() => some(3))).toStrictEqual(some(3));
expect(y.orElse(() => { throw new Error(); })).toStrictEqual(none());
expect(y.orElse(() => none())).toStrictEqual(none());
replace
Replaces the current value with x and returns the old Option.
This method mutates the Option.
const x = some(2);
const y = none<number>();
expect(x.replace(5)).toStrictEqual(some(2));
expect(x).toStrictEqual(some(5));
expect(y.replace(5)).toStrictEqual(none());
expect(y).toStrictEqual(some(5)); // y is mutated
take
Takes the value out of the Option, leaving None in its place.
This method mutates the Option.
const x = some(2);
const y = none<number>();
expect(x.take()).toStrictEqual(some(2));
expect(x).toStrictEqual(none());
expect(y.take()).toStrictEqual(none());
expect(y).toStrictEqual(none());
takeIf
takeIf(f: (x: T) => boolean): Option<T>
Takes the value out of the Option, but only if f returns true.
Similar to take, but conditional.
- This method mutates the
Option. - If
fthrows,Noneis returned and the original value remains unchanged.
const x = some(2);
const y = none<number>();
const z = some(1);
expect(x.takeIf((n) => n > 0)).toStrictEqual(some(2));
expect(x).toStrictEqual(none());
expect(x.takeIf((n) => n < 0)).toStrictEqual(none());
expect(y.takeIf((n) => n > 0)).toStrictEqual(none());
expect(z.takeIf((_) => { throw new Error(); })).toStrictEqual(none());
expect(z).toStrictEqual(some(1));
tap
tap(f: (x: Option<T>) => unknown): Option<T>
Executes f with a copy of this Option, then returns a new copy unchanged.
Useful for side-effects like logging, works with both Some and None.
- If
fthrows or rejects, the error is ignored. - If
freturns a promise, the promise is not awaited before returning.
const x = some(42);
const y = none<number>();
let log = "";
expect(x.tap((opt) => (log = opt.toString()))).toStrictEqual(some(42));
expect(log).toBe("Some { 42 }");
expect(y.tap((opt) => (log = opt.toString()))).toStrictEqual(none());
expect(log).toBe("None");
toPending
toPending(): PendingOption<Awaited<T>>
Maps the option to a PendingOption by supplying a shallow
copy of the option to a PendingOption factory.
Useful for transposing an option with PromiseLike value to a
PendingOption with Awaited value.
If inner T is a promise-like that rejects, maps to a PendingOption with None.
const value = { a: 1 };
const x = some(value);
const y = none<number>();
const pendingX = x.toPending();
expect(isPendingOption(pendingX)).toBe(true);
expect(await pendingX).toStrictEqual(some({ a: 1 }));
value.a = 2;
expect(await pendingX).toStrictEqual(some({ a: 2 }));
expect(await y.toPending()).toStrictEqual(none());
toPendingCloned
toPendingCloned(this: Option<Cloneable<T>>): PendingOption<Awaited<T>>
Maps this option to a PendingOption by supplying
a clone of the option to PendingOption factory.
Useful for transposing an option with PromiseLike value to a
PendingOption with Awaited value.
If inner T is a promise-like that rejects, maps to a PendingOption with None.
class CloneableClass implements Clone<CloneableClass> {
constructor(public a: number) {}
clone(this: Clone<CloneableClass>): CloneableClass;
clone(this: CloneableClass): CloneableClass;
clone(): CloneableClass {
return new CloneableClass(this.a);
}
}
const value = new CloneableClass(0);
const x = some(value);
const y = none<number>();
const pendingX = x.toPendingCloned();
expect(isPendingOption(pendingX)).toBe(true);
expect((await pendingX).unwrap().a).toBe(0);
value.a = 42;
expect((await pendingX).unwrap().a).toBe(0);
expect(await y.toPendingCloned()).toStrictEqual(none());
toString
Returns a string representation of the Option.
const x = some(2);
const y = none<number>();
expect(x.toString()).toBe("Some { 2 }");
expect(y.toString()).toBe("None");
transpose
transpose<U, E>(this: Option<Result<U, E>>): Result<Option<U>, E>
Transposes an Option of a Result into a Result of an Option.
Maps None to Ok(None), Some(Ok(_)) to Ok(Some(_)), and Some(Err(_)) to Err(_).
Only available on Options that hold a Result value.
const x = none<Result<number, string>>();
const y = some<Result<number, string>>(ok(2));
const z = some<Result<number, string>>(err("error"));
expect(x.transpose()).toStrictEqual(ok(none()));
expect(y.transpose()).toStrictEqual(ok(some(2)));
expect(z.transpose()).toStrictEqual(err("error"));
unwrap
unwrap(this: SettledOption<T>): T
Returns the value if Some, or throws an OptionError if None.
Only available on Options that are Settled.
Throws OptionError if this is None
const x = some(2);
const y = none<number>();
expect(x.unwrap()).toBe(2);
expect(() => y.unwrap()).toThrow("`unwrap`: called on `None`");
unwrapOr
unwrapOr(this: SettledOption<T>, def: Awaited<T>): T
Returns the contained value if Some, or def if None.
Only available on Options that are Settled.
const x = some(2);
const y = none<number>();
expect(x.unwrapOr(0)).toBe(2);
expect(y.unwrapOr(0)).toBe(0);
unwrapOrElse
unwrapOrElse(this: SettledOption<T>, mkDef: () => Awaited<T>): T
Returns the contained value if Some, or the result of mkDef if None.
Only available on Options that are Settled.
Throws OptionError if mkDef throws. Original error will be set as
OptionError.reason.
const x = some(2);
const y = none<number>();
expect(x.unwrapOrElse(() => 0)).toBe(2);
expect(y.unwrapOrElse(() => 0)).toBe(0);
expect(() => y.unwrapOrElse(() => { throw new Error(); })).toThrow(OptionError);
xor
Returns Some (or PendingOption with Some, when y is a promise)
if exactly one of this or y is Some, otherwise returns None.
const x = some(2);
const y = none<number>();
expect(x.xor(some(3))).toStrictEqual(none());
expect(x.xor(none())).toStrictEqual(some(2));
expect(y.xor(some(3))).toStrictEqual(some(3));
expect(y.xor(none())).toStrictEqual(none());
expect(isPendingOption(x.xor(Promise.resolve(some(3))))).toBe(true);
expect(await x.xor(Promise.resolve(some(3)))).toStrictEqual(none());
expect(await x.xor(Promise.resolve(none()))).toStrictEqual(some(2));
expect(await y.xor(Promise.resolve(some(3)))).toStrictEqual(some(3));