Either overview
Added in v2.0.0
Table of contents
- combining
- constructors
- do notation
- equivalence
- error handling
- filtering & conditionals
- generators
- getters
- guards
- lifting
- mapping
- models
- pattern matching
- sequencing
- symbols
- type lambdas
- utils
- zipping
combining
all
Takes a structure of Either
s and returns an Either
of values with the same structure.
- If a tuple is supplied, then the returned
Either
will contain a tuple with the same length. - If a struct is supplied, then the returned
Either
will contain a struct with the same keys. - If an iterable is supplied, then the returned
Either
will contain an array.
Signature
export declare const all: <const I extends Iterable<Either<any, any>> | Record<string, Either<any, any>>>(
input: I
) => [I] extends [ReadonlyArray<Either<any, any>>]
? Either<
{ -readonly [K in keyof I]: [I[K]] extends [Either<infer R, any>] ? R : never },
I[number] extends never ? never : [I[number]] extends [Either<any, infer L>] ? L : never
>
: [I] extends [Iterable<Either<infer R, infer L>>]
? Either<Array<R>, L>
: Either<
{ -readonly [K in keyof I]: [I[K]] extends [Either<infer R, any>] ? R : never },
I[keyof I] extends never ? never : [I[keyof I]] extends [Either<any, infer L>] ? L : never
>
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.all([Either.right(1), Either.right(2)]), Either.right([1, 2]))
assert.deepStrictEqual(
Either.all({ right: Either.right(1), b: Either.right("hello") }),
Either.right({ right: 1, b: "hello" })
)
assert.deepStrictEqual(Either.all({ right: Either.right(1), b: Either.left("error") }), Either.left("error"))
Added in v2.0.0
ap
Signature
export declare const ap: {
<R, L2>(that: Either<R, L2>): <R2, L>(self: Either<(right: R) => R2, L>) => Either<R2, L | L2>
<R, R2, L, L2>(self: Either<(right: R) => R2, L>, that: Either<R, L2>): Either<R2, L | L2>
}
Added in v2.0.0
constructors
fromNullable
Takes a lazy default and a nullable value, if the value is not nully (null
or undefined
), turn it into a Right
, if the value is nully use the provided default as a Left
.
Signature
export declare const fromNullable: {
<R, L>(onNullable: (right: R) => L): (self: R) => Either<NonNullable<R>, L>
<R, L>(self: R, onNullable: (right: R) => L): Either<NonNullable<R>, L>
}
Example
import { Either } from "effect"
assert.deepStrictEqual(
Either.fromNullable(1, () => "fallback"),
Either.right(1)
)
assert.deepStrictEqual(
Either.fromNullable(null, () => "fallback"),
Either.left("fallback")
)
Added in v2.0.0
fromOption
Signature
export declare const fromOption: {
<L>(onNone: () => L): <R>(self: Option<R>) => Either<R, L>
<R, L>(self: Option<R>, onNone: () => L): Either<R, L>
}
Example
import { Either, Option } from "effect"
assert.deepStrictEqual(
Either.fromOption(Option.some(1), () => "error"),
Either.right(1)
)
assert.deepStrictEqual(
Either.fromOption(Option.none(), () => "error"),
Either.left("error")
)
Added in v2.0.0
left
Constructs a new Either
holding a Left
value. This usually represents a failure, due to the right-bias of this structure.
Signature
export declare const left: <L>(left: L) => Either<never, L>
Added in v2.0.0
right
Constructs a new Either
holding a Right
value. This usually represents a successful value due to the right bias of this structure.
Signature
export declare const right: <R>(right: R) => Either<R>
Added in v2.0.0
try
Imports a synchronous side-effect into a pure Either
value, translating any thrown exceptions into typed failed eithers creating with Either.left
.
Signature
export declare const try: { <R, L>(options: { readonly try: LazyArg<R>; readonly catch: (error: unknown) => L; }): Either<R, L>; <R>(evaluate: LazyArg<R>): Either<R, unknown>; }
Added in v2.0.0
do notation
Do
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Signature
export declare const Do: Either<{}, never>
Example
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
Added in v2.0.0
bind
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Signature
export declare const bind: {
<N extends string, A extends object, B, L2>(
name: Exclude<N, keyof A>,
f: (a: NoInfer<A>) => Either<B, L2>
): <L1>(self: Either<A, L1>) => Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
<A extends object, L1, N extends string, B, L2>(
self: Either<A, L1>,
name: Exclude<N, keyof A>,
f: (a: NoInfer<A>) => Either<B, L2>
): Either<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, L1 | L2>
}
Example
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
Added in v2.0.0
bindTo
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Signature
export declare const bindTo: {
<N extends string>(name: N): <R, L>(self: Either<R, L>) => Either<{ [K in N]: R }, L>
<R, L, N extends string>(self: Either<R, L>, name: N): Either<{ [K in N]: R }, L>
}
Example
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
Added in v2.0.0
let
The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind
and let
.
Here’s how the do simulation works:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEither
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - Inside the do simulation scope, you can also use the
let
function to define variables and bind them to simple values
Signature
export declare const let: {
<N extends string, R extends object, B>(
name: Exclude<N, keyof R>,
f: (r: NoInfer<R>) => B
): <L>(self: Either<R, L>) => Either<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
<R extends object, L, N extends string, B>(
self: Either<R, L>,
name: Exclude<N, keyof R>,
f: (r: NoInfer<R>) => B
): Either<{ [K in N | keyof R]: K extends keyof R ? R[K] : B }, L>
}
Example
import { Either, pipe } from "effect"
const result = pipe(
Either.Do,
Either.bind("x", () => Either.right(2)),
Either.bind("y", () => Either.right(3)),
Either.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(result, Either.right({ x: 2, y: 3, sum: 5 }))
Added in v2.0.0
equivalence
getEquivalence
Signature
export declare const getEquivalence: <R, L>({
left,
right
}: {
right: Equivalence.Equivalence<R>
left: Equivalence.Equivalence<L>
}) => Equivalence.Equivalence<Either<R, L>>
Added in v2.0.0
error handling
orElse
Returns self
if it is a Right
or that
otherwise.
Signature
export declare const orElse: {
<L, R2, L2>(that: (left: L) => Either<R2, L2>): <R>(self: Either<R, L>) => Either<R | R2, L2>
<R, L, R2, L2>(self: Either<R, L>, that: (left: L) => Either<R2, L2>): Either<R | R2, L2>
}
Added in v2.0.0
filtering & conditionals
filterOrLeft
Filter the right value with the provided function. If the predicate fails, set the left value with the result of the provided function.
Signature
export declare const filterOrLeft: {
<R, B extends R, L2>(
refinement: Refinement<NoInfer<R>, B>,
orLeftWith: (right: NoInfer<R>) => L2
): <L>(self: Either<R, L>) => Either<B, L2 | L>
<R, L2>(
predicate: Predicate<NoInfer<R>>,
orLeftWith: (right: NoInfer<R>) => L2
): <L>(self: Either<R, L>) => Either<R, L2 | L>
<R, L, B extends R, L2>(
self: Either<R, L>,
refinement: Refinement<R, B>,
orLeftWith: (right: R) => L2
): Either<B, L | L2>
<R, L, E2>(self: Either<R, L>, predicate: Predicate<R>, orLeftWith: (right: R) => E2): Either<R, L | E2>
}
Example
import { pipe, Either } from "effect"
const isPositive = (n: number): boolean => n > 0
assert.deepStrictEqual(
pipe(
Either.right(1),
Either.filterOrLeft(isPositive, (n) => `${n} is not positive`)
),
Either.right(1)
)
assert.deepStrictEqual(
pipe(
Either.right(0),
Either.filterOrLeft(isPositive, (n) => `${n} is not positive`)
),
Either.left("0 is not positive")
)
Added in v2.0.0
generators
gen
Signature
export declare const gen: Gen.Gen<EitherTypeLambda, Gen.Adapter<EitherTypeLambda>>
Added in v2.0.0
getters
getLeft
Converts a Either
to an Option
discarding the value.
Signature
export declare const getLeft: <R, L>(self: Either<R, L>) => Option<L>
Example
import { Either, Option } from "effect"
assert.deepStrictEqual(Either.getLeft(Either.right("ok")), Option.none())
assert.deepStrictEqual(Either.getLeft(Either.left("err")), Option.some("err"))
Added in v2.0.0
getOrElse
Returns the wrapped value if it’s a Right
or a default value if is a Left
.
Signature
export declare const getOrElse: {
<L, R2>(onLeft: (left: L) => R2): <R>(self: Either<R, L>) => R2 | R
<R, L, R2>(self: Either<R, L>, onLeft: (left: L) => R2): R | R2
}
Example
import { Either } from "effect"
assert.deepStrictEqual(
Either.getOrElse(Either.right(1), (error) => error + "!"),
1
)
assert.deepStrictEqual(
Either.getOrElse(Either.left("not a number"), (error) => error + "!"),
"not a number!"
)
Added in v2.0.0
getOrNull
Signature
export declare const getOrNull: <R, L>(self: Either<R, L>) => R | null
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrNull(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrNull(Either.left("a")), null)
Added in v2.0.0
getOrThrow
Extracts the value of an Either
or throws if the Either
is Left
.
The thrown error is a default error. To configure the error thrown, see {@link getOrThrowWith}.
Signature
export declare const getOrThrow: <R, L>(self: Either<R, L>) => R
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrThrow(Either.right(1)), 1)
assert.throws(() => Either.getOrThrow(Either.left("error")))
Added in v2.0.0
getOrThrowWith
Extracts the value of an Either
or throws if the Either
is Left
.
If a default error is sufficient for your use case and you don’t need to configure the thrown error, see {@link getOrThrow}.
Signature
export declare const getOrThrowWith: {
<L>(onLeft: (left: L) => unknown): <A>(self: Either<A, L>) => A
<R, L>(self: Either<R, L>, onLeft: (left: L) => unknown): R
}
Example
import { Either } from "effect"
assert.deepStrictEqual(
Either.getOrThrowWith(Either.right(1), () => new Error("Unexpected Left")),
1
)
assert.throws(() => Either.getOrThrowWith(Either.left("error"), () => new Error("Unexpected Left")))
Added in v2.0.0
getOrUndefined
Signature
export declare const getOrUndefined: <R, L>(self: Either<R, L>) => R | undefined
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.getOrUndefined(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrUndefined(Either.left("a")), undefined)
Added in v2.0.0
getRight
Converts a Either
to an Option
discarding the Left
.
Signature
export declare const getRight: <R, L>(self: Either<R, L>) => Option<R>
Example
import { Either, Option } from "effect"
assert.deepStrictEqual(Either.getRight(Either.right("ok")), Option.some("ok"))
assert.deepStrictEqual(Either.getRight(Either.left("err")), Option.none())
Added in v2.0.0
merge
Signature
export declare const merge: <R, L>(self: Either<R, L>) => L | R
Added in v2.0.0
guards
isEither
Tests if a value is a Either
.
Signature
export declare const isEither: (input: unknown) => input is Either<unknown, unknown>
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.isEither(Either.right(1)), true)
assert.deepStrictEqual(Either.isEither(Either.left("a")), true)
assert.deepStrictEqual(Either.isEither({ right: 1 }), false)
Added in v2.0.0
isLeft
Determine if a Either
is a Left
.
Signature
export declare const isLeft: <R, L>(self: Either<R, L>) => self is Left<L, R>
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.isLeft(Either.right(1)), false)
assert.deepStrictEqual(Either.isLeft(Either.left("a")), true)
Added in v2.0.0
isRight
Determine if a Either
is a Right
.
Signature
export declare const isRight: <R, L>(self: Either<R, L>) => self is Right<L, R>
Example
import { Either } from "effect"
assert.deepStrictEqual(Either.isRight(Either.right(1)), true)
assert.deepStrictEqual(Either.isRight(Either.left("a")), false)
Added in v2.0.0
lifting
liftPredicate
Transforms a Predicate
function into a Right
of the input value if the predicate returns true
or Left
of the result of the provided function if the predicate returns false
Signature
export declare const liftPredicate: {
<A, B extends A, E>(refinement: Refinement<NoInfer<A>, B>, orLeftWith: (a: NoInfer<A>) => E): (a: A) => Either<B, E>
<A, E>(predicate: Predicate<NoInfer<A>>, orLeftWith: (a: NoInfer<A>) => E): (a: A) => Either<A, E>
<A, E, B extends A>(self: A, refinement: Refinement<A, B>, orLeftWith: (a: A) => E): Either<B, E>
<A, E>(self: A, predicate: Predicate<NoInfer<A>>, orLeftWith: (a: NoInfer<A>) => E): Either<A, E>
}
Example
import { pipe, Either } from "effect"
const isPositive = (n: number): boolean => n > 0
assert.deepStrictEqual(
pipe(
1,
Either.liftPredicate(isPositive, (n) => `${n} is not positive`)
),
Either.right(1)
)
assert.deepStrictEqual(
pipe(
0,
Either.liftPredicate(isPositive, (n) => `${n} is not positive`)
),
Either.left("0 is not positive")
)
Added in v3.4.0
mapping
flip
Returns an Either
that swaps the error/success cases. This allows you to use all methods on the error channel, possibly before flipping back.
Signature
export declare const flip: <R, L>(self: Either<R, L>) => Either<L, R>
Added in v2.0.0
map
Maps the Right
side of an Either
value to a new Either
value.
Signature
export declare const map: {
<R, R2>(f: (right: R) => R2): <L>(self: Either<R, L>) => Either<R2, L>
<R, L, R2>(self: Either<R, L>, f: (right: R) => R2): Either<R2, L>
}
Added in v2.0.0
mapBoth
Signature
export declare const mapBoth: {
<L, L2, R, R2>(options: {
readonly onLeft: (left: L) => L2
readonly onRight: (right: R) => R2
}): (self: Either<R, L>) => Either<R2, L2>
<L, R, L2, R2>(
self: Either<R, L>,
options: { readonly onLeft: (left: L) => L2; readonly onRight: (right: R) => R2 }
): Either<R2, L2>
}
Added in v2.0.0
mapLeft
Maps the Left
side of an Either
value to a new Either
value.
Signature
export declare const mapLeft: {
<L, L2>(f: (left: L) => L2): <R>(self: Either<R, L>) => Either<R, L2>
<R, L, L2>(self: Either<R, L>, f: (left: L) => L2): Either<R, L2>
}
Added in v2.0.0
models
Either (type alias)
Signature
export type Either<R, L = never> = Left<L, R> | Right<L, R>
Added in v2.0.0
EitherUnify (interface)
Signature
export interface EitherUnify<A extends { [Unify.typeSymbol]?: any }> {
Either?: () => A[Unify.typeSymbol] extends Either<infer R0, infer L0> | infer _ ? Either<R0, L0> : never
}
Added in v2.0.0
EitherUnifyIgnore (interface)
Signature
export interface EitherUnifyIgnore {}
Added in v2.0.0
Left (interface)
Signature
export interface Left<out L, out R> extends Pipeable, Inspectable {
readonly _tag: "Left"
readonly _op: "Left"
readonly left: L
readonly [TypeId]: {
readonly _R: Covariant<R>
readonly _L: Covariant<L>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: EitherUnify<this>
[Unify.ignoreSymbol]?: EitherUnifyIgnore
}
Added in v2.0.0
Right (interface)
Signature
export interface Right<out L, out R> extends Pipeable, Inspectable {
readonly _tag: "Right"
readonly _op: "Right"
readonly right: R
readonly [TypeId]: {
readonly _R: Covariant<R>
readonly _L: Covariant<L>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: EitherUnify<this>
[Unify.ignoreSymbol]?: EitherUnifyIgnore
}
Added in v2.0.0
pattern matching
match
Takes two functions and an Either
value, if the value is a Left
the inner value is applied to the onLeft function, if the value is a
Rightthe inner value is applied to the
onRight` function.
Signature
export declare const match: {
<L, B, R, C = B>(options: {
readonly onLeft: (left: L) => B
readonly onRight: (right: R) => C
}): (self: Either<R, L>) => B | C
<R, L, B, C = B>(
self: Either<R, L>,
options: { readonly onLeft: (left: L) => B; readonly onRight: (right: R) => C }
): B | C
}
Example
import { pipe, Either } from "effect"
const onLeft = (strings: ReadonlyArray<string>): string => `strings: ${strings.join(", ")}`
const onRight = (value: number): string => `Ok: ${value}`
assert.deepStrictEqual(pipe(Either.right(1), Either.match({ onLeft, onRight })), "Ok: 1")
assert.deepStrictEqual(
pipe(Either.left(["string 1", "string 2"]), Either.match({ onLeft, onRight })),
"strings: string 1, string 2"
)
Added in v2.0.0
sequencing
andThen
Executes a sequence of two Either
s. The second Either
can be dependent on the result of the first Either
.
Signature
export declare const andThen: {
<R, R2, L2>(f: (right: R) => Either<R2, L2>): <L>(self: Either<R, L>) => Either<R2, L | L2>
<R2, L2>(f: Either<R2, L2>): <L, R1>(self: Either<R1, L>) => Either<R2, L | L2>
<R, R2>(f: (right: R) => R2): <L>(self: Either<R, L>) => Either<R2, L>
<R2>(right: NotFunction<R2>): <R1, L>(self: Either<R1, L>) => Either<R2, L>
<R, L, R2, L2>(self: Either<R, L>, f: (right: R) => Either<R2, L2>): Either<R2, L | L2>
<R, L, R2, L2>(self: Either<R, L>, f: Either<R2, L2>): Either<R2, L | L2>
<R, L, R2>(self: Either<R, L>, f: (right: R) => R2): Either<R2, L>
<R, L, R2>(self: Either<R, L>, f: NotFunction<R2>): Either<R2, L>
}
Added in v2.0.0
flatMap
Signature
export declare const flatMap: {
<R, R2, L2>(f: (right: R) => Either<R2, L2>): <L>(self: Either<R, L>) => Either<R2, L | L2>
<R, L, R2, L2>(self: Either<R, L>, f: (right: R) => Either<R2, L2>): Either<R2, L | L2>
}
Added in v2.0.0
symbols
TypeId
Signature
export declare const TypeId: typeof TypeId
Added in v2.0.0
TypeId (type alias)
Signature
export type TypeId = typeof TypeId
Added in v2.0.0
type lambdas
EitherTypeLambda (interface)
Signature
export interface EitherTypeLambda extends TypeLambda {
readonly type: Either<this["Target"], this["Out1"]>
}
Added in v2.0.0
utils
Either (namespace)
Added in v2.0.0
Left (type alias)
Signature
export type Left<T extends Either<any, any>> = [T] extends [Either<infer _A, infer _E>] ? _E : never
Added in v2.0.0
Right (type alias)
Signature
export type Right<T extends Either<any, any>> = [T] extends [Either<infer _A, infer _E>] ? _A : never
Added in v2.0.0
zipping
zipWith
Signature
export declare const zipWith: {
<R2, L2, R, B>(that: Either<R2, L2>, f: (right: R, right2: R2) => B): <L>(self: Either<R, L>) => Either<B, L2 | L>
<R, L, R2, L2, B>(self: Either<R, L>, that: Either<R2, L2>, f: (right: R, right2: R2) => B): Either<B, L | L2>
}
Added in v2.0.0