@sweet-monads/either
Either Monad, The Either monad represents values with two possibilities: a value of type Either a b is either Left a or Right b.
This library belongs to sweet-monads project
sweet-monads — easy-to-use monads implementation with static types definition and separated packages.
- No dependencies, one small file
- Easily auditable TypeScript/JS code
- Check out all libraries:
maybe,
iterator,
interfaces,
Usage
npm install @sweet-monads/either
import { Either, right } from "@sweet-monads/either";
class UserNotFoundError extends Error { name: "UserNotFoundError" };
type User = { email: string, password: string };
function getUser(id: number): Either<UserNotFoundError, User> {
return right({ email: "test@gmail.com", password: "test" });
}
const user = getUser(1).map(({ email }) => email);
API
merge
function merge<L1, R1>(values: [Either<L1, R1>]): Either<L1, [R1]>;
function merge<L1, R1, L2, R2>(values: [Either<L1, R1>, Either<L2, R2>]): Either<L1 | L2, [R1, R2]>;
function merge<L1, R1, L2, R2, L3, R3>(values: [Either<L1, R1>, Either<L2, R2>, Either<L3, R3>]): Either<L1 | L2 | L3, [R1, R2, R3]>;
values: Array<Either<L, R>>
- Array of Either values which will be merged into Either of Array- Returns
Either<L, Array<R>>
which will contain Right<Array<R>>
if all of array elements was Right<R>
otherwise Left<L>
.
Example:
const v1 = right<TypeError, number>(2);
const v2 = right<ReferenceError, string>("test");
const v3 = left<Error, boolean>(new Error());
merge([v1, v2])
merge([v1, v2, v3])
left
function left<L, R>(value: L): Either<L, R>;
- Returns
Either
with Left
state which contain value with L
type.
Example:
const v2 = left(new Error());
const v2 = left<Error, number>(new Error());
right
function right<L, R>(value: R): Either<L, R>;
- Returns
Either
with Right
state which contain value with R
type.
Example:
const v2 = right(2);
const v2 = right<Error, number>(2);
from
The same as right
Return only Right
typed value.
function from<R>(value: R): Either<unknown, R>;
- Returns
Either
with Right
state which contain value with R
type.
Example:
from(2);
isEither
function isEither<L, R>(value: unknown | Maybe<L, R>): value is Maybe<L, R>;
- Returns
boolean
if given value
is instance of Either constructor.
Example:
const value: unknown = 2;
if (isEither(value)) {
}
Either#isLeft
function isLeft(): boolean;
- Returns
true
if state of Either
is Left
otherwise false
Example:
const v1 = right(2);
const v2 = left(2);
v1.isLeft()
v2.isLeft()
Either#isRight
function isRight(): boolean;
- Returns
true
if state of Either
is Right
otherwise false
Example:
const v1 = right(2);
const v2 = left(2);
v1.isRight()
v2.isRight()
Either#or
function or<L, R>(x: Either<L, R>): Either<L, R>;
- Returns
Either<L, R>
. If state of this
is Right
then this
will be returned otherwise x
argument will be returned
Example:
const v1 = right<number, string>(2);
const v2 = left<number, string>("Error 1");
const v3 = left<number, string>("Error 2");
const v4 = right<number, string>(3);
v1.or(v2)
v2.or(v1)
v2.or(v3)
v1.or(v4)
v2.or(v3).or(v1)
v2.or(v1).or(v3)
v1.or(v2).or(v3)
Either#join
function join<L1, L2, R>(this: Either<L1, Either<L2, R>>): Either<L1 | L2, R>;
this: Either<L1, Either<L2, R>>
- Either
instance which contains other Either
instance as Right
value.- Returns unwrapped
Either
- if current Either
has Right
state and inner Either
has Right
state then returns inner Either
Right
, if inner Either
has Left
state then return inner Either
Left
otherwise outer Either
Left
.
Example:
const v1 = right(right(2));
const v2 = right(left(new Error()));
const v3 = left<TypeError, Either<Error, number>>(new TypeError());
v1.join()
v2.join()
v3.join()
Either#map
function map<L, R, NewR>(fn: (val: R) => NewR): Either<L, NewR>;
- Returns mapped by
fn
function value wrapped by Either
if Either
is Right
otherwise Left
with L
value
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.map(a => a.toString());
const newVal2 = v2.map(a => a.toString());
Either#mapRight
function mapRight<L, R, NewR>(fn: (val: R) => NewR): Either<L, NewR>;
The same as Either#map
- Returns mapped by
fn
function value wrapped by Either
if Either
is Right
otherwise Left
with L
value
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.map(a => a.toString());
const newVal2 = v2.map(a => a.toString());
Either#mapLeft
function mapLeft<L, R, NewL>(fn: (val: L) => NewL): Either<NewL, R>;
- Returns mapped by
fn
function value wrapped by Either
if Either
is Left
otherwise Right
with R
value
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.mapLeft(a => a.toString());
const newVal2 = v2.mapLeft(a => a.toString());
Either#asyncMap
function asyncMap<L, R, NewR>(fn: (val: R) => Promise<NewR>): Promise<Either<L, NewR>>;
- Returns
Promise
with mapped by fn
function value wrapped by Either
if Either
is Right
otherwise Left
with value L
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.asyncMap(a => Promise.resolve(a.toString()));
const newVal2 = v2.asyncMap(a => Promise.resolve(a.toString()));
Either#apply
function apply<A, B>(this: Either<L, (a: A) => B>, arg: Either<L, A>): Either<L, B>;
function apply<A, B>(this: Either<L, A>, fn: Either<L, (a: A) => B>): Either<L, B>;
this | fn
- function wrapped by Either, which should be applied to value arg
arg | this
- value which should be applied to fn
- Returns mapped by
fn
function value wrapped by Either
if Either
is Right
otherwise Left
with L
value
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const fn1 = right<Error, (a: number) => number>((a: number) => a * 2);
const fn2 = left<Error, (a: number) => number>(new Error());
const newVal1 = fn1.apply(v1);
const newVal2 = fn1.apply(v2);
const newVal3 = fn2.apply(v1);
const newVal4 = fn2.apply(v2);
Either#asyncApply
Async variant of Either#apply
function asyncApply<A, B>(this: Maybe<(a: Promise<A> | A) => Promise<B>>, arg: Maybe<Promise<A> | A>): Promise<Maybe<B>>;
function asyncApply<A, B>(this: Maybe<Promise<A> | A>, fn: Maybe<(a: Promise<A> | A) => Promise<B>>): Promise<Maybe<B>>;
this | fn
- function wrapped by Maybe, which should be applied to value arg
arg | this
- value which should be applied to fn
- Returns
Promise
with mapped by fn
function value wrapped by Either
if Either
is Right
otherwise Left
with L
value
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const fn1 = right<Error, (a: number) => Promise<number>>((a: number) => Promise.resolve(a * 2));
const fn2 = left<Error, (a: number) => Promise<number>>(new Error());
const newVal1 = fn1.apply(v1);
const newVal2 = fn1.apply(v2);
const newVal3 = fn2.apply(v1);
const newVal4 = fn2.apply(v2);
Either#chain
function chain<L, R, NewL, NewR>(fn: (val: R) => Either<NewL, NewR>): Either<L | newL, NewR>;
- Returns mapped by
fn
function value wrapped by Either
if Either
is Right
and returned by fn
value is Right
too otherwise Left
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.chain(a => right<TypeError, string>(a.toString()));
const newVal2 = v1.chain(a => left<TypeError, string>(new TypeError()));
const newVal3 = v2.chain(a => right<TypeError, string>(a.toString()));
const newVal4 = v2.chain(a => left<TypeError, string>(new TypeError()));
Either#asyncChain
function chain<L, R, NewL, NewR>(fn: (val: R) => Promise<Either<NewL, NewR>>): Promise<Either<L | newL, NewR>>;
- Returns
Promise
with mapped by fn
function value wrapped by Either
if Either
is Right
and returned by fn
value is Right
too otherwise Left
Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());
const newVal1 = v1.chain(a => right<TypeError, string>(a.toString()));
const newVal2 = v1.chain(a => left<TypeError, string>(new TypeError()));
const newVal3 = v2.chain(a => right<TypeError, string>(a.toString()));
const newVal4 = v2.chain(a => left<TypeError, string>(new TypeError()));
Helpers
const { value } = right<Error, number>(2);
const { value } = right(2);
const { value } = left<Error, number>(new Error());
const { value } = left(2);
License
MIT (c) Artem Kobzar see LICENSE file.