Skip to content

Either

47 exports Added in v2.0.0 Source

Combining

all

Added in v2.0.0 Source

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.

Signature

declare const all: <I extends Iterable<Either<any, any>> | Record<string, Either<any, any>>>(
  input: I,
) => [I] extends [ReadonlyArray<Either<any, any>>]
  ? Either<
      { [K in keyof I]: [I[K]] extends [Either<infer A, any>] ? A : never },
      I[number] extends never ? never : [I[number]] extends [Either<any, infer E>] ? E : never
    >
  : [I] extends [Iterable<Either<infer A, infer E>>]
    ? Either<Array<A>, E>
    : Either<
        { [K in keyof I]: [I[K]] extends [Either<infer A, any>] ? A : never },
        I[keyof I] extends never ? never : [I[keyof I]] extends [Either<any, infer E>] ? E : never
      >;

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"),
)

ap

Added in v2.0.0 Source

Signature

declare const ap: {
  <A, E2>(that: Either<A, E2>): <A2, E>(self: Either<(right: A) => A2, E>) => Either<A2, E2 | E>;
  <A, A2, E, E2>(self: Either<(right: A) => A2, E>, that: Either<A, E2>): Either<A2, E | E2>;
};

Constructors

fromNullable

Added in v2.0.0 Source

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

declare const fromNullable: {
  <A, E>(onNullable: (right: A) => E): (self: A) => Either<NonNullable<A>, E>;
  <A, E>(self: A, onNullable: (right: A) => E): Either<NonNullable<A>, E>;
};

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"),
)

fromOption

Added in v2.0.0 Source

Signature

declare const fromOption: {
  <E>(onNone: () => E): <A>(self: Option<A>) => Either<A, E>;
  <A, E>(self: Option<A>, onNone: () => E): Either<A, E>;
};

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"),
)

left

Added in v2.0.0 Source

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: <E>(e: E) => Either<never, E>;

Do Notation

bind

Added in v2.0.0 Source

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

See

Signature

declare const bind: {
  <N extends string, A extends object, B, E2>(
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => Either<B, E2>,
  ): <E>(
    self: Either<A, E>,
  ) => Either<{ [K in string | number | symbol]: K extends keyof A ? A[K] : B }, E2 | E>;
  <A extends object, E, N extends string, B, E2>(
    self: Either<A, E>,
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => Either<B, E2>,
  ): Either<{ [K in string | number | symbol]: K extends keyof A ? A[K] : B }, E | E2>;
};

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

bindTo

Added in v2.0.0 Source

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

See

Signature

declare const bindTo: {
  <N extends string>(name: N): <A, E>(self: Either<A, E>) => Either<{ [K in string]: A }, E>;
  <A, E, N extends string>(self: Either<A, E>, name: N): Either<{ [K in string]: A }, E>;
};

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

Do

Added in v2.0.0 Source

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

See

Signature

declare const Do: Either<{}>;

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

Equivalence

Signature

declare function getEquivalence<A, E>(__namedParameters: {
  left: Equivalence<E>;
  right: Equivalence<A>;
}): Equivalence<Either<A, E>>;

Error Handling

orElse

Added in v2.0.0 Source

Returns self if it is a Right or that otherwise.

Signature

declare const orElse: {
  <E, A2, E2>(that: (left: E) => Either<A2, E2>): <A>(self: Either<A, E>) => Either<A2 | A, E2>;
  <A, E, A2, E2>(self: Either<A, E>, that: (left: E) => Either<A2, E2>): Either<A | A2, E2>;
};

Filtering & Conditionals

filterOrLeft

Added in v2.0.0 Source

Filter the right value with the provided function. If the predicate fails, set the left value with the result of the provided function.

Signature

declare const filterOrLeft: {
  <A, B, E2>(
    refinement: Refinement<NoInfer<A>, B>,
    orLeftWith: (right: NoInfer<A>) => E2,
  ): <E>(self: Either<A, E>) => Either<B, E2 | E>;
  <A, E2>(
    predicate: Predicate<NoInfer<A>>,
    orLeftWith: (right: NoInfer<A>) => E2,
  ): <E>(self: Either<A, E>) => Either<A, E2 | E>;
  <A, E, B, E2>(
    self: Either<A, E>,
    refinement: Refinement<A, B>,
    orLeftWith: (right: A) => E2,
  ): Either<B, E | E2>;
  <A, E, E2>(
    self: Either<A, E>,
    predicate: Predicate<A>,
    orLeftWith: (right: A) => E2,
  ): Either<A, E | E2>;
};

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"),
)

Generators

gen

Added in v2.0.0 Source

Signature

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

Getters

getLeft

Added in v2.0.0 Source

Converts a Either to an Option discarding the value.

Signature

declare const getLeft: <A, E>(self: Either<A, E>) => Option<E>;

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

getOrElse

Added in v2.0.0 Source

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

Signature

declare const getOrElse: {
  <E, A2>(onLeft: (left: E) => A2): <A>(self: Either<A, E>) => A2 | A;
  <A, E, A2>(self: Either<A, E>, onLeft: (left: E) => A2): A | A2;
};

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!",
)

getOrNull

Added in v2.0.0 Source

Signature

declare const getOrNull: <A, E>(self: Either<A, E>) => A | null;

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)

getOrThrow

Added in v2.0.0 Source

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.

Signature

declare const getOrThrow: <A, E>(self: Either<A, E>) => A;

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

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.

Signature

declare const getOrThrowWith: {
  <E>(onLeft: (left: E) => unknown): <A>(self: Either<A, E>) => A;
  <A, E>(self: Either<A, E>, onLeft: (left: E) => unknown): A;
};

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 getOrUndefined: <A, E>(self: Either<A, E>) => A | undefined;

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)

getRight

Added in v2.0.0 Source

Converts a Either to an Option discarding the Left.

Signature

declare const getRight: <A, E>(self: Either<A, E>) => Option<A>;

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

merge

Added in v2.0.0 Source

Signature

declare const merge: <A, E>(self: Either<A, E>) => E | A;

Guards

isEither

Added in v2.0.0 Source

Tests if a value is a Either.

Signature

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

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)

isLeft

Added in v2.0.0 Source

Determine if a Either is a Left.

Signature

declare const isLeft: <A, E>(self: Either<A, E>) => self is Left<E, A>;

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)

isRight

Added in v2.0.0 Source

Determine if a Either is a Right.

Signature

declare const isRight: <A, E>(self: Either<A, E>) => self is Right<E, A>;

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)

Lifting

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

declare const liftPredicate: {
  <A, B, E>(refinement: Refinement<A, B>, orLeftWith: (a: A) => E): (a: A) => Either<B, E>;
  <B, E, A = B>(predicate: Predicate<A>, orLeftWith: (a: A) => E): (a: B) => Either<B, E>;
  <A, E, B>(self: A, refinement: Refinement<A, B>, orLeftWith: (a: A) => E): Either<B, E>;
  <B, E, A = B>(self: B, predicate: Predicate<A>, orLeftWith: (a: A) => E): Either<B, E>;
};

Example

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

const isPositive = (n: number): boolean => n > 0
const isPositiveEither = Either.liftPredicate(isPositive, (n) => `${n} is not positive`)

assert.deepStrictEqual(isPositiveEither(1), Either.right(1))
assert.deepStrictEqual(isPositiveEither(0), Either.left("0 is not positive"))

Mapping

flip

Added in v2.0.0 Source

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 function flip<A, E>(self: Either<A, E>): Either<E, A>;

map

Added in v2.0.0 Source

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

Signature

declare const map: {
  <A, A2>(f: (right: A) => A2): <E>(self: Either<A, E>) => Either<A2, E>;
  <A, E, A2>(self: Either<A, E>, f: (right: A) => A2): Either<A2, E>;
};

mapBoth

Added in v2.0.0 Source

Signature

declare const mapBoth: {
  <E, E2, A, A2>(options: {
    readonly onLeft: (left: E) => E2;
    readonly onRight: (right: A) => A2;
  }): (self: Either<A, E>) => Either<A2, E2>;
  <A, E, E2, A2>(
    self: Either<A, E>,
    options: {
      readonly onLeft: (left: E) => E2;
      readonly onRight: (right: A) => A2;
    },
  ): Either<A2, E2>;
};

mapLeft

Added in v2.0.0 Source

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

Signature

declare const mapLeft: {
  <E, E2>(f: (left: E) => E2): <A>(self: Either<A, E>) => Either<A, E2>;
  <A, E, E2>(self: Either<A, E>, f: (left: E) => E2): Either<A, E2>;
};

Models

Either type

Added in v2.0.0 Source

Signature

type Either<A, E = never> = Left<E, A> | Right<E, A>;

EitherUnify interface

Added in v2.0.0 Source

Signature

interface EitherUnify<
  A extends {
    [typeSymbol]?: any;
  },
> {
  Either?: () => A[typeof typeSymbol] extends Either<R0, L0> | _ ? Either<R0, L0> : never;
}

EitherUnifyIgnore interface

Added in v2.0.0 Source

Signature

interface EitherUnifyIgnore {
  Effect?: true;
  Option?: true;
  Tag?: true;
}

Left interface

Added in v2.0.0 Source

Signature

interface Left<out E, out A> extends Pipeable, Inspectable, STM<A, E>, Effect<A, E> {
  readonly _op: "Left";
  readonly _tag: "Left";
  readonly [ChannelTypeId]: VarianceStruct<never, unknown, E, unknown, A, unknown, never>;
  readonly [EffectTypeId]: VarianceStruct<A, E, never>;
  [ignoreSymbol]?: EitherUnifyIgnore;
  readonly [SinkTypeId]: VarianceStruct<A, unknown, never, E, never>;
  readonly [STMTypeId]: {
    readonly _A: Covariant<A>;
    readonly _E: Covariant<E>;
    readonly _R: Covariant<never>;
  };
  readonly [StreamTypeId]: VarianceStruct<A, E, never>;
  readonly [TypeId]: {
    readonly _L: Covariant<E>;
    readonly _R: Covariant<A>;
  };
  [typeSymbol]?: unknown;
  [unifySymbol]?: EitherUnify<Left<E, A>>;
  readonly left: E;
  [iterator](): EffectGenerator<Left<E, A>>;
}

Optional Wrapping & Unwrapping

Applies an Either on an Option and transposes the result.

Details

If the Option is None, the resulting Either will immediately succeed with a Right value of None. If the Option is Some, the transformation function will be applied to the inner value, and its result wrapped in a Some.

Signature

declare const transposeMapOption: <A, B, E = never>(f: (self: A) => Either<B, E>) => (self: Option<A>) => Either<Option<B>, E> & <A, B, E = never>(self: Option<A>, f: (self: A) => Either<B, E>) => Either<Option<B>, E>

Example

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

//          โ”Œโ”€โ”€โ”€ Either<Option<number>, never>>
//          โ–ผ
const noneResult = pipe(
  Option.none(),
  Either.transposeMapOption(() => Either.right(42)), // will not be executed
)
console.log(noneResult)
// Output: { _id: 'Either', _tag: 'Right', right: { _id: 'Option', _tag: 'None' } }

//          โ”Œโ”€โ”€โ”€ Either<Option<number>, never>>
//          โ–ผ
const someRightResult = pipe(
  Option.some(42),
  Either.transposeMapOption((value) => Either.right(value * 2)),
)
console.log(someRightResult)
// Output: { _id: 'Either', _tag: 'Right', right: { _id: 'Option', _tag: 'Some', value: 84 } }

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.

Signature

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

Other

Either

Added in v2.0.0 Source

Signature

declare const let: {
  <N extends string, A extends object, B>(
    name: Exclude<N, keyof A>,
    f: (r: NoInfer<A>) => B,
  ): <E>(
    self: Either<A, E>,
  ) => Either<{ [K in string | number | symbol]: K extends keyof A ? A[K] : B }, E>;
  <A extends object, E, N extends string, B>(
    self: Either<A, E>,
    name: Exclude<N, keyof A>,
    f: (r: NoInfer<A>) => B,
  ): Either<{ [K in string | number | symbol]: K extends keyof A ? A[K] : B }, E>;
};

Signature

declare const try: {
  <A, E>(options: {
    readonly catch: (error: unknown) => E;
    readonly try: LazyArg<A>;
  }): Either<A, E>;
  <A>(evaluate: LazyArg<A>): Either<A, unknown>;
}

Signature

declare const void: Either<void>

Pattern Matching

match

Added in v2.0.0 Source

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 Right the inner value is applied to the onRight` function.

Signature

declare const match: {
  <E, B, A, C = B>(options: {
    readonly onLeft: (left: E) => B;
    readonly onRight: (right: A) => C;
  }): (self: Either<A, E>) => B | C;
  <A, E, B, C = B>(
    self: Either<A, E>,
    options: {
      readonly onLeft: (left: E) => B;
      readonly onRight: (right: A) => C;
    },
  ): B | C;
};

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",
)

Sequencing

andThen

Added in v2.0.0 Source

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

Signature

declare const andThen: {
  <A, A2, E2>(f: (right: A) => Either<A2, E2>): <E>(self: Either<A, E>) => Either<A2, E2 | E>;
  <A2, E2>(f: Either<A2, E2>): <E, A>(self: Either<A, E>) => Either<A2, E2 | E>;
  <A, A2>(f: (right: A) => A2): <E>(self: Either<A, E>) => Either<A2, E>;
  <A2>(right: NotFunction<A2>): <A, E>(self: Either<A, E>) => Either<A2, E>;
  <A, E, A2, E2>(self: Either<A, E>, f: (right: A) => Either<A2, E2>): Either<A2, E | E2>;
  <A, E, A2, E2>(self: Either<A, E>, f: Either<A2, E2>): Either<A2, E | E2>;
  <A, E, A2>(self: Either<A, E>, f: (right: A) => A2): Either<A2, E>;
  <A, E, A2>(self: Either<A, E>, f: NotFunction<A2>): Either<A2, E>;
};

flatMap

Added in v2.0.0 Source

Signature

declare const flatMap: {
  <A, A2, E2>(f: (right: A) => Either<A2, E2>): <E>(self: Either<A, E>) => Either<A2, E2 | E>;
  <A, E, A2, E2>(self: Either<A, E>, f: (right: A) => Either<A2, E2>): Either<A2, E | E2>;
};

Symbols

TypeId

Added in v2.0.0 Source

Signature

declare const TypeId: unique symbol;

TypeId type

Added in v2.0.0 Source

Signature

type TypeId = typeof TypeId;

Type Lambdas

EitherTypeLambda interface

Added in v2.0.0 Source

Signature

interface EitherTypeLambda extends TypeLambda {
  readonly type: Either<unknown, unknown>;
}

Zipping

zipWith

Added in v2.0.0 Source

Signature

declare const zipWith: {
  <A2, E2, A, B>(
    that: Either<A2, E2>,
    f: (right: A, right2: A2) => B,
  ): <E>(self: Either<A, E>) => Either<B, E2 | E>;
  <A, E, A2, E2, B>(
    self: Either<A, E>,
    that: Either<A2, E2>,
    f: (right: A, right2: A2) => B,
  ): Either<B, E | E2>;
};