Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sweet-monads/either

Package Overview
Dependencies
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sweet-monads/either

Either monad

  • 3.3.1
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
5.8K
decreased by-0.82%
Maintainers
1
Weekly downloads
 
Created
Source

@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: either, iterator, interfaces, maybe

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" });
}

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

FAQs

Package last updated on 29 Aug 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc