npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sweet-monads/either

v3.3.1

Published

Either monad

Downloads

26,106

Readme

@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.

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: "[email protected]", password: "test" });
}

// Either<UserNotFoundError, string>
const user = getUser(1).map(({ email }) => email);

API

chain

function chain<L, R, NL, NR>(fn: (v: R) => Promise<Either<NL, NR>>): (m: Either<L, R>) => Promise<Either<L | NL, NR>>;
  • fn: (v: R) => Promise<Either<NL, NR>> - function which should be applied asynchronously to Either<L, R> value
  • Returns function with Either<L, R> argument and promised Either with new error or mapped by fn value (could be used inside Promise#then function).

Example:

const getValue = async () => right(1);

// Either<TypeError, right>
const result = await getValue()
  .then(Either.chain(async v => right(v * 2)))
  .then(Either.chain(async v => left(new TypeError("Unexpected"))));

merge

Alias for mergeInOne

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]>;
// ... until 10 elements
  • 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); // Either<TypeError, number>.Right
const v2 = right<ReferenceError, string>("test"); // Either<ReferenceError, string>.Right
const v3 = left<Error, boolean>(new Error()); // Either<Error, boolean>.Left

merge([v1, v2]); // Either<TypeError | ReferenceError, [number, string]>.Right
merge([v1, v2, v3]); // Either<TypeError | ReferenceError | Error, [number, string, boolean]>.Left

mergeInOne

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]>;
// ... until 10 elements
  • 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); // Either<TypeError, number>.Right
const v2 = right<ReferenceError, string>("test"); // Either<ReferenceError, string>.Right
const v3 = left<Error, boolean>(new Error()); // Either<Error, boolean>.Left

merge([v1, v2]); // Either<TypeError | ReferenceError, [number, string]>.Right
merge([v1, v2, v3]); // Either<TypeError | ReferenceError | Error, [number, string, boolean]>.Left

mergeInMany

function mergeInMany<L1, R1>(values: [Either<L1, R1>]): Either<Array<L1>, [R1]>;
function mergeInMany<L1, R1, L2, R2>(values: [Either<L1, R1>, Either<L2, R2>]): Either<Array<L1 | L2>, [R1, R2]>;
function mergeInMany<L1, R1, L2, R2, L3, R3>(
  values: [Either<L1, R1>, Either<L2, R2>, Either<L3, R3>]
): Either<Array<L1 | L2 | L3>, [R1, R2, R3]>;
// ... until 10 elements
  • values: Array<Either<L, R>> - Array of Either values which will be merged into Either of Array
  • Returns Either<Array<L>, Array<R>> which will contain Right<Array<R>> if all of array elements was Right<R> otherwise array of all caught Left<L> values.

Example:

const v1 = right<TypeError, number>(2); // Either<TypeError, number>.Right
const v2 = right<ReferenceError, string>("test"); // Either<ReferenceError, string>.Right
const v3 = left<Error, boolean>(new Error()); // Either<Error, boolean>.Left

merge([v1, v2]); // Either<Array<TypeError | ReferenceError>, [number, string]>.Right
merge([v1, v2, v3]); // Either<Array<TypeError | ReferenceError | Error>, [number, string, boolean]>.Left

left

function left<L, R>(value: L): Either<L, R>;
  • Returns Either with Left state which contain value with L type. Example:
const v1 = left(new Error()); // Either<Error, never>.Left
const v2 = left<Error, number>(new Error()); // Either<Error, number>.Left

right

function right<L, R>(value: R): Either<L, R>;
  • Returns Either with Right state which contain value with R type. Example:
const v1 = right(2); // Either<never, number>.Right
const v2 = right<Error, number>(2); // Either<Error, number>.Right

from

The same as right

Return only Right typed value.

function from<R>(value: R): Either<never, R>;
  • Returns Either with Right state which contain value with R type. Example:
from(2); // Either<never, number>.Right

fromTry

Returns Right with function result or Left if function execution throws an error.

function fromTry<L, R>(fn: () => R): Either<L, R>;
fromTry(() => 2); // Either<never, number>.Right
fromTry(() => {
  throw new Error("test");
}); // Either<Error, never>.Left

fromPromise

Returns Right with the promise value if the provided promise fulfilled or Left with the error value if the provided promise rejected.

function fromPromise<L, R>(promise: Promise<R>): Promise<Either<L, R>>;
fromPromise(Promise.resolve(2)); // Either<never, number>.Right
fromPromise(Promise.reject(new Error("test"))); // Either<Error, never>.Left

isEither

function isEither<L, R>(value: unknown | Either<L, R>): value is Either<L, R>;
  • Returns boolean if given value is instance of Either constructor. Example:
const value: unknown = 2;
if (isEither(value)) {
  // ... value is Either<unknown, unknown> at this block
}

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(); // false
v2.isLeft(); // true

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(); // true
v2.isRight(); // false

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<string, number>(2);
const v2 = left<string, number>("Error 1");
const v3 = left<string, number>("Error 2");
const v4 = right<string, number>(3);

v1.or(v2); // v1 will be returned
v2.or(v1); // v1 will be returned
v2.or(v3); // v3 will be returned
v1.or(v4); // v1 will be returned

v2.or(v3).or(v1); // v1 will be returned
v2.or(v1).or(v3); // v1 will be returned
v1.or(v2).or(v3); // v1 will be returned

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(); // Either.Right with value 2
v2.join(); // Either.Left with value new Error
v3.join(); // Either.Left with value new TypeError

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()); // Either<Error, string>.Right with value "2"
const newVal2 = v2.map(a => a.toString()); // Either<Error, string>.Left with value new Error()

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()); // Either<Error, string>.Right with value "2"
const newVal2 = v2.map(a => a.toString()); // Either<Error, string>.Left with value new Error()

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()); // Either<string, number>.Right with value 2
const newVal2 = v2.mapLeft(a => a.toString()); // Either<string, number>.Left with value "Error"
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());

// Promise<Either<Error, string>.Right> with value "2"
const newVal1 = v1.asyncMap(a => Promise.resolve(a.toString()));
// Promise<Either<Error, string>.Left> with value new Error()
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); // Either<Error, number>.Right with value 4
const newVal2 = fn1.apply(v2); // Either<Error, number>.Left with value new Error()
const newVal3 = fn2.apply(v1); // Either<Error, number>.Left with value new Error()
const newVal4 = fn2.apply(v2); // Either<Error, number>.Left with value new Error()
Either#asyncApply

Async variant of Either#apply

function asyncApply<A, B>(this: Either<L, (a: A) => Promise<B>>, arg: Either<L, Promise<A> | A>): Promise<Either<L, B>>;
function asyncApply<A, B>(this: Either<L, Promise<A> | A>, fn: Either<L, (a: A) => Promise<B>>): Promise<Either<L, B>>;
function asyncApply<A, B>(
  this: Either<L, Promise<A> | A> | Either<L, (a: A) => Promise<B>>,
  argOrFn: Either<L, Promise<A> | A> | Either<L, (a: A) => Promise<B>>
): Promise<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 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); // Promise<Either<Error, number>.Right> with value 4
const newVal2 = fn1.apply(v2); // Promise<Either<Error, number>.Left> with value new Error()
const newVal3 = fn2.apply(v1); // Promise<Either<Error, number>.Left> with value new Error()
const newVal4 = fn2.apply(v2); // Promise<Either<Error, number>.Left> with value new Error()

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());

// Either<Error | TypeError, string>.Right with value "2"
const newVal1 = v1.chain(a => right<TypeError, string>(a.toString()));
// Either<Error | TypeError, string>.Left with value new TypeError()
const newVal2 = v1.chain(a => left<TypeError, string>(new TypeError()));
// Either<Error | TypeError, string>.Left with value new Error()
const newVal3 = v2.chain(a => right<TypeError, string>(a.toString()));
// Either<Error | TypeError, string>.Left with value new Error()
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());

// Promise<Either<Error | TypeError, string>.Right> with value "2"
const newVal1 = v1.asyncChain(a => right<TypeError, string>(a.toString()));
// Promise<Either<Error | TypeError, string>.Left> with value new TypeError()
const newVal2 = v1.asyncChain(a => left<TypeError, string>(new TypeError()));
// Promise<Either<Error | TypeError, string>.Left> with value new Error()
const newVal3 = v2.asyncChain(a => right<TypeError, string>(a.toString()));
// Promise<Either<Error | TypeError, string>.Left> with value new Error()
const newVal4 = v2.chain(a => left<TypeError, string>(new TypeError()));
Either#fold
function fold<C>(mapLeft: (value: L) => C, mapRight: (value: R) => C): C;
  • Returns values mapped by mapRight if Either is Right, otherwise value mapped by mapLeft Example:
const v1 = right<Error, number>(2);
const v2 = left<Error, number>(new Error());

// 4
const newVal1 = v1.fold(() => 'fail', value => value * 2);
// "fail"
const newVal2 = v2.fold(() => 'fail', value => value * 2);

Helpers

// Value from Either instance
const { value } = right<Error, number>(2); // number | Error
const { value } = right(2); // number
const { value } = left<Error, number>(new Error()); // number | Error
const { value } = left(new Error()); // Error
right(2).unwrap(); // number
left(new TypeError()).unwrap(); // throws error

right(2).unwrap(); // number
left(new TypeError()).unwrap(x => x); // throws TypeError provied in arguments

left(2).unwrapOr(3) // returns 3
rigth(2).unwrapOr(3) // returns 2

left(2).unwrapOrElse(num => num * 2) // returns 4
right(2).unwrapOrElse(num => num * 2) // returns 2

License

MIT (c) Artem Kobzar see LICENSE file.