An ergonomic way to work with fallible operations in TypeScript.
API Reference
·
Report Bug
·
Request Feature
·
Road map
- ✨ Fully type-safe, and ergonomic API that uses popular conventions.
- 🎉 Comes with a clean and easy to use way to simulate the do-notation.
- ⚡️ Tree-shakable, works with esm, cjs, and doesn't force you to use
nodenext
/node16
module resolution.
npm install this-is-ok
yarn add this-is-ok
pnpm add this-is-ok
// an example of adapting a standard library function to use Option
const safeParseInt = (value: string): Option<number> => {
const parsed = parseInt(value);
if (isNaN(parsed)) {
return none;
}
return some(parsed);
};
// `of` from the option module creates an Option from a nullable value
of(localStorage.getItem("counter"))
// map the inner value to another Option
.flatMap((d) => safeParseInt(d))
// map the inner value or use a default value if it's none
.mapOr(0, (d) => d + 1)
// perform any side effect with the value
.tap((d) => localStorage.setItem("counter", d.toString()));
Do notation lets us write the "happy path" of a function without having to worry about the error handling.
We access the inner values of options by calling bind
on them, and if any point, inside the do
block, bind
is called on none
then we short-circuit the execution and none is returned.
some(1)
.do((value) => {
const a = some(2).bind();
const b = some("hello").bind();
return some(b.repeat(value + a));
})
.tap(console, log); // "hellohellohello"
some(1).do((value) => {
const a = value; // 1
const b = some(2).bind(); // 2
const c = (none as Option<number>).bind();
// the execution stops here and none is returned
// so the following lines are not executed
const d = some(3).bind();
return some(a + b + c + d);
}).isNone; // true
- Option
- Creation
- Methods
isSome: boolean
isSomeAnd: (predicate: (value: T) => boolean) => boolean
isNone: boolean
expect: (message: string) => T
unwrap: () => T
unwrapOr: (defaultValue: T) => T
unwrapOrElse: (defaultValueFun: () => T) => T
map: <U>(f: (value: T) => U) => Option<U>
mapOr: <U>(defaultValue: U, f: (value: T) => U) => U
mapOrElse: <U>(defaultValueFun: () => U, f: (arg: T) => U) => U
okOr: <E>(err: E) => Result<T, E>
okOrElse: <E>(f: () => E) => Result<T, E>
and: <U>(b: Option<U>) => Option<U>
or: (b: Option<T>) => Option<T>
orElse: (f: () => Option<T>) => Option<T>
flatMap: <U>(f: (value: T) => Option<U>) => Option<U>
andThen: <U>(f: (value: T) => Option<U>) => Option<U>
tap: <F extends void | Promise<void>>(f: (value: T) => F) => F
filter: (predicate: (arg: T) => boolean) => Option<T>
match: <U>(pattern: { some: (value: T) => U; none: () => U }) => U
do: <U>(f: (value: T) => Option<U>) => Option<U>
- Result
- Creation
- Methods
isOk: boolean
isOkAnd: (predicate: (value: T) => boolean) => boolean
isErr: boolean
isErrAnd: (predicate: (value: E) => boolean) => boolean
ok: () => Option<T>
err: () => Option<T>
expect: (message: string) => T
unwrap: () => T
expectErr: (message: string) => T
unwrapErr: () => E
unwrapOr: (defaultValue: T) => T
unwrapOrElse: (defaultValueFun: () => T) => T
map: <U>(f: (value: T) => U) => Result<U, E>
mapOr: <U>(defaultValue: U, f: (value: T) => U) => U
mapOrElse: <U>(defaultValueFun: () => U, f: (arg: T) => U) => U
mapErr: <U>(f: (value: E) => U) => Result<T, U>
and: <U>(b: Result<U, E>) => Result<U, E>
or: <F>(b: Result<T, F>) => Result<T,F>
orElse: <F>(f: () => Result<T, F>) => Result<T, F>
flatMap: <U>(f: (value: T) => Result<U, E>) => Result<U, E>
andThen: <U>(f: (value: T) => Result<U, E>) => Result<U, E>
do: <U, F>(f: (value: T) => Result<U, F>) => Result<U, F>
match: <U>(pattern: { ok: (value: T) => U; err: (value: E) => U }) => U
Converts a nullable value into an option.
Example:
of(1); // some(1)
of(null); // none
of(undefined); // none
Calls a function and converts its result into an option. If the function is null or undefined or it throws an exception, none is returned.
Example:
from(() => 1); // some(1)
from(() => null); // none
from(() => {
throw new Error("oopsie hehe");
}); // none
Property that is true
if the option is a Some
variant and false
otherwise.
Example:
some(3).isSome; // true
none.isSome; // false
Returns true if the option is a Some variant and the value inside of it matches a predicate.
Example:
expect(some(42).isSomeAnd((v) => v % 2)).toBe(true);
expect(some(42).isSomeAnd((v) => v > 100)).toBe(true);
Property that is true
if the option is a None
variant and false
otherwise.
Example:
expect(none.isNone).toBe(true);
expect(some(42).isNone).toBe(false);
Returns the inner value. Useful for situations where if the
option is a None
then there is no tap to continue running the program.
The message can be used for debugging purposes.
Parameters:
message
- The message to throw if the option is aNone
variant.
Throws:
Throws the given message if the option is a None
variant.
Example:
expect(some(42).expect("should be a number")).toBe(42);
expect(none.expect("this will throw")).toThrow();
Returns the inner value or throws an Error if the option is a None
variant.
Throws:
Throws if the option is a None
variant.
Example:
expect(some(42).unwrap()).toBe(42);
expect(none.unwrap()).toThrow();
Returns the inner value or the provided default value.
Example:
expect(some(42).unwrapOr(1)).toBe(42);
expect(none.unwrapOr(1)).toBe(1);
Returns the inner value or computes it from a function.
Example:
expect(some(42).unwrapOrElse(() => 1)).toBe(42);
expect(none.unwrapOrElse(() => 1)).toBe(1);
Maps an Option<T>
to Option<U>
by applying a function to a contained
value (if Some) or returns None (if None).
Example:
expect(
some(42)
.map((x) => x + 1)
.unwrap()
).toBe(43);
expect(none.map((x) => x + 1).isNone()).toBe(true);
Returns the provided default result (if none), or applies a function to the contained value (if any).
Example:
expect(
some(42)
.mapOr(10, (x) => x + 1)
.unwrap()
).toBe(43);
expect(none.mapOr(10, (x) => x + 1).unwrap()).toBe(11);
Computes a default function result (if none), or applies a different function to the contained value (if any).
Example:
expect(
some(42)
.mapOrElse(
() => 10,
(x) => x + 1
)
.unwrap()
).toBe(43);
expect(
none
.mapOrElse(
() => 10,
(x) => x + 1
)
.unwrap()
).toBe(11);
Given an error: E
converts Option<T>
to Result<T, E>
.
Example:
some(42).okOr("error"); // { variant: "ok", value: 42, ... }
none.okOr("error"); // { variant: "error", error: "error", ... }
Same as okOr
but the error is computed from a function.
Returns None if the option is None, otherwise returns b
.
Example:
expect(some(42).and(some(1)).unwrap()).toBe(1);
expect(none.and(some(1)).is
None()).toBe(true);
Returns None if the option is None, otherwise returns b
.
Example:
expect(some(42).or(some(1)).unwrap()).toBe(43);
expect(none.or(some(1)).unwrap()).toBe(1);
Returns the option if it contains a value, otherwise calls f and returns the result.
Example:
expect(
some(42)
.orElse(() => some(1))
.unwrap()
).toBe(42);
expect(none.orElse(() => some(1)).unwrap()).toBe(1);
Returns None if the option is None, otherwise calls f with the wrapped value and returns the result.
Example:
expect(
some(42)
.flatMap((x) => some(x + 1))
.unwrap()
).toBe(43);
expect(
some(42)
.flatMap((x) => none)
.isNone()
).toBe(true);
Returns None if the option is None, otherwise calls f with the wrapped value and returns the result.
Example:
expect(
some(42)
.andThen((x) => some(x + 1))
.unwrap()
).toBe(43);
expect(
some(42)
.andThen((x) => none)
.isNone()
).toBe(true);
Runs the given void function with the inner value if the option is a Some
variant
or does nothing if the option is a None
variant.
Example:
expect(
some(42)
.tap((x) => some(x + 1))
.unwrap()
).toBe(43);
expect(
some(42)
.tap((x) => none)
.isNone()
).toBe(true);
Returns None if the option is None, otherwise returns None
if the predicate predicate
returns false
when applied to the contained
value, otherwise returns the Option<T>
.
Example:
expect(
some(42)
.filter((x) => x > 10)
.unwrap()
).toBe(42);
expect(
some(42)
.filter((x) => x < 10)
.isNone()
).toBe(true);
Allows you to run different functions depending on the variant of the option.
Example:
expect(
some(3).match({
some: (d) => d + 1,
none: () => 0,
})
).toBe(4);
expect(
none.match({
some: (d) => d + 1,
none: () => 0,
})
).toBe(0);
Lets you simulate a do-notation known from functional languages with the Option monad.
Example:
expect(
some(1)
.do((value) => {
const a = value;
const b = some(2).bind();
const c = some(3).bind();
return some(a + b + c);
})
.unwrap()
).toBe(6);
Creates a new Result<T, E>
from a possibly nullable value and an error.
Example:
expect(of(42, "error").unwrap()).toBe(42);
expect(of({}, "error").unwrap()).toEqual({});
expect(of(NaN, "error").unwrap()).toEqual(NaN);
expect(of("", "error").unwrap()).toEqual("");
expect(of(null, "error").isErr).toBe(true);
expect(of(undefined, "error").isErr).toBe(true);
Creates a new Result<T, E>
from a function that can throw and an error.
Example:
expect(from(() => 42, "error").unwrap()).toBe(42);
expect(from(() => ({}), "error").unwrap()).toEqual({});
expect(from(() => NaN, "error").unwrap()).toEqual(NaN);
expect(from(() => "", "error").unwrap()).toEqual("");
expect(from(() => null, "error").isErr).toBe(true);
expect(from(() => undefined, "error").isErr).toBe(true);
expect(
from(() => {
throw "error";
}, "error").isErr
).toBe(true);
Creates a new Result<T, E>
from a function that can throw.
If the function returns any value (including null
and undefined
) it is wrapped in an Ok
variant. If the function throws an error it is wrapped in an Err
variant. Errors that are not of type Error
are wrapped in an Error
object.
Example:
expect(fromThrowable(() => 42).unwrap()).toBe(42);
expect(fromThrowable(() => ({})).unwrap()).toEqual({});
expect(fromThrowable(() => NaN).unwrap()).toEqual(NaN);
expect(fromThrowable(() => "").unwrap()).toEqual("");
expect(fromThrowable(() => null).unwrap()).toEqual(null);
expect(fromThrowable(() => undefined).unwrap()).toEqual(undefined);
const a = fromThrowable(() => {
throw "error";
});
expect(a.unwrapErr()).toEqual(new Error("error"));
const b = fromThrowable(() => {
throw new Error("error");
});
expect(b.unwrapErr()).toEqual(new Error("error"));
Property that is true
if the result is Ok.
Example:
expect(ok(42).isOk).toBe(true);
expect(err("error").isOk).toBe(false);
Returns true
if the result is an Ok variant and the value inside of it matches a predicate.
Example:
expect(some(42).isSomeAnd((v) => v % 2)).toBe(true);
expect(some(42).isSomeAnd((v) => v > 100)).toBe(true);
Property that is true
if the result is Err.
Example:
expect(ok(42).isErr).toBe(false);
expect(err("error").isErr).toBe(true);
Returns true
if the result is an Err variant and the value inside of it matches a predicate.
Example:
expect(some(42).isSomeAnd((v) => v % 2)).toBe(true);
expect(some(42).isSomeAnd((v) => v > 100)).toBe(true);
Converts from Result<T, E> to Option discarding the error, if any.
Example:
expect(ok(42).ok()).toEqual(some(42));
expect(err("error").ok()).toEqual(none);
Converts from Result<T, E> to Option discarding the error, if any.
Example:
expect(ok(42).ok()).toEqual(some(42));
expect(err("error").ok()).toEqual(none);
Returns the inner value. Useful for situations where if the result is an Err
then there is no use to continue running the program. The message can be used for debugging purposes.
message
: The message to throw if the option is anErr
variant.
Throws:
- Throws the given message if the option is an
Err
variant.
Example:
expect(ok(42).expect("should be a number")).toBe(42);
expect(err("error").expect("this will throw")).toThrow();
Returns the Ok value or throws an Error if the result is an Err
variant.
Throws:
- Throws if the option is a
None
variant.
Example:
expect(ok(42).unwrap()).toBe(42)
expect(err("error").unwrap().toThrow()
Returns the contained Err value or throws an error if the result is an Ok
variant.
message
: The message to throw if the option is anOk
variant.
Throws:
- Throws the given message if the option is an
Ok
variant.
Example:
expect(err(42).expectErr("should be a number")).toBe(42);
expect(ok(42).expectErr("this will throw")).toThrow();
Returns the contained Err value or throws an error if the result is an Ok
variant.
Throws:
- Throws if the option is a
None
variant.
**Example
:**
expect(err("error").unwrapErr()).toBe(42)
expect(ok(42).unwrapErr().toThrow()
Returns the Ok value or the provided default value.
defaultValue
: The default value to return if the result is anErr
variant.
Example:
expect(ok(42).unwrapOr(1)).toBe(42)
expect(err("error").unwrapOr(1).toBe(1)
Returns the Ok value or computes it from a function.
defaultValueFun
: The function that computes the default value if the result is anErr
variant.
Example:
expect(ok(42).unwrapOrElse(() => 1)).toBe(42)
expect(err("error").unwrapOrElse(() => 1).toBe(1)
Maps a Result<T, E> to Result<U, E> by applying a function to a contained Ok value, leaving an Err value untouched.
Example:
expect(
ok(42)
.map((x) => x + 1)
.unwrap()
).toBe(43);
expect(
err("error")
.map((x) => x + 1)
.isNone()
).toBe(true);
Returns the provided default (if Err), or applies a function to the contained value (if Ok).
defaultValue
: The default value to return if the result is anErr
variant.f
: The function to apply to the contained value if the result is anOk
variant.
Example:
expect(ok(42).mapOr(10, (x) => x + 1)).toBe(43);
expect(error("error").mapOr(10, (x) => x + 1)).toBe(11);
Maps a Result<T, E> to U by applying a fallback function default to a contained Err value, or function f to a contained Ok value.
defaultValueFun
: The fallback function to apply to the contained Err value.f
: The function to apply to the contained Ok value.
Example:
expect(ok(42).mapOrElse(() => 10, (x) => x + 1))).toBe(43)
expect(error("error").mapOrElse(() => 10, (x) => x + 1))).toBe(11)
Maps a Result<T, E> to Result<T, F> by applying a function to a contained Err value, leaving an Ok value untouched.
Example:
expect(
ok(42)
.map((x) => x + 1)
.unwrap()
).toBe(43);
expect(
err("error")
.map((x) => x + 1)
.isNone()
).toBe(true);
Returns res
if the result is Ok, otherwise returns the Err value of self.
b
: The Result value to return if the current result is Ok.
Returns res
if the result is Err, otherwise returns the Ok value of self.
b
: The Result value to return if the current result is Err.
Returns the option if it contains a value, otherwise calls f
and returns the result.
f
: The function to call if the result is anErr
variant.
Returns err
if the Result
is err
, otherwise calls
f with the wrapped value and returns the result.
Example:
// same as andThen
expect(okVariant.flatMap((v) => ok(v + 1)).unwrap()).toBe(43);
expect(okVariant.flatMap((v) => err("error")).unwrapErr()).toBe("error");
expect(errVariant.flatMap((v) => ok(v + 1)).unwrapErr()).toBe("error");
expect(errVariant.flatMap((v) => err("error1")).unwrapErr()).toBe("error");
Alias for flatMap
.
Similar to do for Option
Similar to match for Option
- Task monad for async operations
- Use github releases
- Add function syntax and make them curried (e.g.
map(maybeNumber, x => x + 1)
) apart from method syntax (e.g.maybeNumber.map(x => x + 1)
) - add adapters for common built-in APIs such as
Map
offs
module.