Skip to main content Link Search Menu Expand Document (external link)

Either.ts overview

Since v2.0.0


Exports Grouped by Category


Optional Wrapping & Unwrapping

transposeOption

Converts an Option of an Either into an Either of an Option.

Details

This function transforms an Option<Either<A, E>> into an Either<Option<A>, E>. If the Option is None, the resulting Either will be a Right with a None value. If the Option is Some, the inner Either will be executed, and its result wrapped in a Some.

Example

import { Effect, Either, Option } from "effect"

//      ┌─── Option<Either<number, never>>
//      ▼
const maybe = Option.some(Either.right(42))

//      ┌─── Either<Option<number>, never, never>
//      ▼
const result = Either.transposeOption(maybe)

console.log(Effect.runSync(result))
// Output: { _id: 'Option', _tag: 'Some', value: 42 }

Signature

declare const transposeOption: <A = never, E = never>(self: Option<Either<A, E>>) => Either<Option<A>, E>

Source

Since v3.14.0

combining

all

Takes a structure of Eithers 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.

Example

import * as assert from "node:assert"
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"))

Signature

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
      >

Source

Since v2.0.0

ap

Signature

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>
}

Source

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

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(
  Either.fromNullable(1, () => "fallback"),
  Either.right(1)
)
assert.deepStrictEqual(
  Either.fromNullable(null, () => "fallback"),
  Either.left("fallback")
)

Signature

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>
}

Source

Since v2.0.0

fromOption

Example

import * as assert from "node:assert"
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")
)

Signature

declare const fromOption: {
  <L>(onNone: () => L): <R>(self: Option<R>) => Either<R, L>
  <R, L>(self: Option<R>, onNone: () => L): Either<R, L>
}

Source

Since 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

declare const left: <L>(left: L) => Either<never, L>

Source

Since v2.0.0

Constructs a new Either holding a Right value. This usually represents a successful value due to the right bias of this structure.

Signature

declare const right: <R>(right: R) => Either<R>

Source

Since 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

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

Source

Since v2.0.0

void

Signature

declare const void: Either<void, never>

Source

Since v3.13.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:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Either values
  3. You can accumulate multiple bind statements to define multiple variables within the scope
  4. Inside the do simulation scope, you can also use the let function to define variables and bind them to simple values

Example

import * as assert from "node:assert"
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 }))

See

  • bind
  • bindTo
  • let

Signature

declare const Do: Either<{}, never>

Source

Since 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:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Either values
  3. You can accumulate multiple bind statements to define multiple variables within the scope
  4. Inside the do simulation scope, you can also use the let function to define variables and bind them to simple values

Example

import * as assert from "node:assert"
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 }))

See

  • Do
  • bindTo
  • let

Signature

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>
}

Source

Since 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:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Either values
  3. You can accumulate multiple bind statements to define multiple variables within the scope
  4. Inside the do simulation scope, you can also use the let function to define variables and bind them to simple values

Example

import * as assert from "node:assert"
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 }))

See

  • Do
  • bind
  • let

Signature

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>
}

Source

Since 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:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Either values
  3. You can accumulate multiple bind statements to define multiple variables within the scope
  4. Inside the do simulation scope, you can also use the let function to define variables and bind them to simple values

Example

import * as assert from "node:assert"
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 }))

See

  • Do
  • bindTo
  • bind

Signature

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>
}

Source

Since v2.0.0

equivalence

getEquivalence

Signature

declare const getEquivalence: <R, L>({
  left,
  right
}: {
  right: Equivalence.Equivalence<R>
  left: Equivalence.Equivalence<L>
}) => Equivalence.Equivalence<Either<R, L>>

Source

Since v2.0.0

error handling

orElse

Returns self if it is a Right or that otherwise.

Signature

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>
}

Source

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

Example

import * as assert from "node:assert"
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")
)

Signature

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>
}

Source

Since v2.0.0

generators

gen

Signature

declare const gen: Gen.Gen<EitherTypeLambda, Gen.Adapter<EitherTypeLambda>>

Source

Since v2.0.0

getters

getLeft

Converts a Either to an Option discarding the value.

Example

import * as assert from "node:assert"
import { Either, Option } from "effect"

assert.deepStrictEqual(Either.getLeft(Either.right("ok")), Option.none())
assert.deepStrictEqual(Either.getLeft(Either.left("err")), Option.some("err"))

Signature

declare const getLeft: <R, L>(self: Either<R, L>) => Option<L>

Source

Since v2.0.0

getOrElse

Returns the wrapped value if it’s a Right or a default value if is a Left.

Example

import * as assert from "node:assert"
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!"
)

Signature

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
}

Source

Since v2.0.0

getOrNull

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(Either.getOrNull(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrNull(Either.left("a")), null)

Signature

declare const getOrNull: <R, L>(self: Either<R, L>) => R | null

Source

Since 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 getOrThrowWith.

Throws

Error("getOrThrow called on a Left")

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(Either.getOrThrow(Either.right(1)), 1)
assert.throws(() => Either.getOrThrow(Either.left("error")))

Signature

declare const getOrThrow: <R, L>(self: Either<R, L>) => R

Source

Since 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 getOrThrow.

Example

import * as assert from "node:assert"
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")))

Signature

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
}

Source

Since v2.0.0

getOrUndefined

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(Either.getOrUndefined(Either.right(1)), 1)
assert.deepStrictEqual(Either.getOrUndefined(Either.left("a")), undefined)

Signature

declare const getOrUndefined: <R, L>(self: Either<R, L>) => R | undefined

Source

Since v2.0.0

getRight

Converts a Either to an Option discarding the Left.

Example

import * as assert from "node:assert"
import { Either, Option } from "effect"

assert.deepStrictEqual(Either.getRight(Either.right("ok")), Option.some("ok"))
assert.deepStrictEqual(Either.getRight(Either.left("err")), Option.none())

Signature

declare const getRight: <R, L>(self: Either<R, L>) => Option<R>

Source

Since v2.0.0

merge

Signature

declare const merge: <R, L>(self: Either<R, L>) => L | R

Source

Since v2.0.0

guards

isEither

Tests if a value is a Either.

Example

import * as assert from "node:assert"
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)

Signature

declare const isEither: (input: unknown) => input is Either<unknown, unknown>

Source

Since v2.0.0

isLeft

Determine if a Either is a Left.

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(Either.isLeft(Either.right(1)), false)
assert.deepStrictEqual(Either.isLeft(Either.left("a")), true)

Signature

declare const isLeft: <R, L>(self: Either<R, L>) => self is Left<L, R>

Source

Since v2.0.0

isRight

Determine if a Either is a Right.

Example

import * as assert from "node:assert"
import { Either } from "effect"

assert.deepStrictEqual(Either.isRight(Either.right(1)), true)
assert.deepStrictEqual(Either.isRight(Either.left("a")), false)

Signature

declare const isRight: <R, L>(self: Either<R, L>) => self is Right<L, R>

Source

Since 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

Example

import * as assert from "node:assert"
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")
)

Signature

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>
}

Source

Since 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

declare const flip: <R, L>(self: Either<R, L>) => Either<L, R>

Source

Since v2.0.0

map

Maps the Right side of an Either value to a new Either value.

Signature

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>
}

Source

Since v2.0.0

mapBoth

Signature

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>
}

Source

Since v2.0.0

mapLeft

Maps the Left side of an Either value to a new Either value.

Signature

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>
}

Source

Since v2.0.0

models

Either (type alias)

Signature

type Either<R, L> = Left<L, R> | Right<L, R>

Source

Since 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
}

Source

Since v2.0.0

EitherUnifyIgnore (interface)

Signature

export interface EitherUnifyIgnore {}

Source

Since 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
}

Source

Since 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
}

Source

Since 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 theonRight` function.

Example

import * as assert from "node:assert"
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"
)

Signature

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
}

Source

Since v2.0.0

sequencing

andThen

Executes a sequence of two Eithers. The second Either can be dependent on the result of the first Either.

Signature

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>
}

Source

Since v2.0.0

flatMap

Signature

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>
}

Source

Since v2.0.0

symbols

TypeId

Signature

declare const TypeId: unique symbol

Source

Since v2.0.0

TypeId (type alias)

Signature

type TypeId = typeof TypeId

Source

Since v2.0.0

type lambdas

EitherTypeLambda (interface)

Signature

export interface EitherTypeLambda extends TypeLambda {
  readonly type: Either<this["Target"], this["Out1"]>
}

Source

Since v2.0.0

utils

Either (namespace)

Source

Since v2.0.0

Left (type alias)

Signature

type Left<T> = [T] extends [Either<infer _A, infer _E>] ? _E : never

Source

Since v2.0.0

Right (type alias)

Signature

type Right<T> = [T] extends [Either<infer _A, infer _E>] ? _A : never

Source

Since v2.0.0

zipping

zipWith

Signature

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>
}

Source

Since v2.0.0