Well-typed Either data-structure
yarn add @typed/either
# or
npm install --save @typed/either
All functions are curried!
Either data structure. Extremely useful for handling errors or different logic paths without the use of if-statements.
export type Either<A, B> = Left<A> | Right<B>
Creates an Either<A, B> that is of type Left<A>
See the code
export const left: <A, B = any>(value: A) => Either<A, B> = Left.of
}
Creates an Either<A, B> that is of type Right<B>
See the code
export const of: <A, B = any>(value: A) => Either<B, A> = Right.of
A JSON-serializable Left<A> data-structure.
export interface Left<A> {
readonly '@typed/Left': A
}
Create a Left<A>
See the code
export function of<A>(value: A): Left<A> {
return { '@typed/Left': value }
}
}
A JSON-serializable Right data-structure.
export interface Right<A> {
readonly '@typed/Right': A
}
Creates a Right
See the code
export function of<A>(value: A): Right<A> {
return { '@typed/Right': value }
}
}
Applies the function contains in an Either
to the value contained in a
second Either
.
See the code
export const ap: EitherAp = curry2(__ap)
function __ap<A, B, C>(fn: Either<A, (value: B) => C>, value: Either<A, B>): Either<A, C> {
return chain(f => map(f, value), fn)
}
export type EitherAp = {
<A, B, C>(fn: Either<A, (value: B) => C>, value: Either<A, B>): Either<A, C>
<A, B, C>(fn: Either<A, (value: B) => C>): (value: Either<A, B>) => Either<A, C>
}
Returns a Either
that is the result of calling f
with the resolved
value of another Either
.
See the code
export const chain: EitherChain = curry2(__chain)
function __chain<A, B, C>(f: (value: B) => Either<A, C>, either: Either<A, B>): Either<A, C> {
return isLeft(either) ? either : f(fromRight(either))
}
export type EitherChain = {
<A, B, C>(f: (value: B) => Either<A, C>, either: Either<A, B>): Either<A, C>
<A, B, C>(f: (value: B) => Either<A, C>): (either: Either<A, B>) => Either<A, C>
}
Returns a Either
that is the result of calling f
with the rejected
value of another Either
.
See the code
export const chainLeft: EitherChainLeft = curry2(__chainLeft)
function __chainLeft<A, B, C>(f: (value: A) => Either<C, B>, either: Either<A, B>): Either<C, B> {
return isLeft(either) ? f(fromLeft(either)) : either
}
export type EitherChainLeft = {
<A, B, C>(f: (value: A) => Either<C, B>, either: Either<A, B>): Either<C, B>
<A, B, C>(f: (value: A) => Either<C, B>): (either: Either<A, B>) => Either<C, B>
}
Extracts the value contained in a Left.
See the code
export function fromLeft<A>(left: Left<A>): A {
return left['@typed/Left']
}
Extracts the value contained in a Right.
See the code
export function fromRight<A>(right: Right<A>): A {
return right['@typed/Right']
}
Returns true if an Either<A, B> is type Left<A>
See the code
export function isLeft<A, B>(either: Either<A, B>): either is Left<A> {
return either.hasOwnProperty('@typed/Left')
}
Returns true if an Either<A, B> is type Right<B>
See the code
export function isRight<A, B>(either: Either<A, B>): either is Right<B> {
return either.hasOwnProperty('@typed/Right')
}
Returns a Either
that is the result of calling f
with the resolved
value of another Either
.
See the code
export const map: EitherMap = curry2(__map)
function __map<A, B, C>(f: (value: B) => C, either: Either<A, B>): Either<A, C> {
return chain(value => Either.of(f(value)), either)
}
export type EitherMap = {
<A, B, C>(f: (value: B) => C, either: Either<A, B>): Either<A, C>
<A, B, C>(f: (value: B) => C): (either: Either<A, B>) => Either<A, C>
}
Returns a Either
that is the result of calling f
with the resolved
value of another Either
.
See the code
export const mapLeft: EitherMapLeft = curry2(__mapLeft)
function __mapLeft<A, B, C>(f: (value: A) => C, either: Either<A, B>): Either<C, B> {
return chainLeft(value => Either.left(f(value)), either)
}
export type EitherMapLeft = {
<A, B, C>(f: (value: A) => C, either: Either<A, B>): Either<C, B>
<A, B, C>(f: (value: A) => C): (either: Either<A, B>) => Either<C, B>
}
Swaps the values contained in an Either
.
See the code
export function swap<A, B>(either: Either<A, B>): Either<B, A> {
return isLeft(either) ? Either.of(fromLeft(either)) : Either.left(fromRight(either))
}
Extracts the value from an Either
applying function f
if the Either\<A, B\>
is
Left\<A\>
or function g
if Right\<B\>
.
See the code
export const unpack: Unpack = curry3(__unpack)
function __unpack<A, B, C>(f: (value: A) => C, g: (value: B) => C, either: Either<A, B>): C {
return isLeft(either) ? f(fromLeft(either)) : g(fromRight(either))
}