Skip to main content
The Either data type represents values with two possibilities, typically used for error handling where Left represents failure and Right represents success.

Type Signature

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

interface Left<E, A> {
  readonly _tag: "Left"
  readonly left: E
}

interface Right<E, A> {
  readonly _tag: "Right"
  readonly right: A
}

Creating Eithers

Type Guards

import { Either } from "effect"

const value = Either.right(1)

if (Either.isRight(value)) {
  console.log(value.right)  // 1
}

if (Either.isLeft(value)) {
  console.log(value.left)
}

Pattern Matching

match

Handle both Left and Right cases.
import { Either } from "effect"

const onLeft = (strings: ReadonlyArray<string>): string => 
  `strings: ${strings.join(', ')}`

const onRight = (value: number): string => 
  `Ok: ${value}`

const result = Either.match(Either.right(1), {
  onLeft,
  onRight
})
// "Ok: 1"

const error = Either.match(
  Either.left(['string 1', 'string 2']),
  { onLeft, onRight }
)
// "strings: string 1, string 2"

Transformations

map

Transforms the Right value.
import { Either } from "effect"

const result = Either.right(2).pipe(
  Either.map(n => n * 2)
)
// Right(4)

mapLeft

Transforms the Left value.
import { Either } from "effect"

const result = Either.left("error").pipe(
  Either.mapLeft(e => `Error: ${e}`)
)
// Left("Error: error")

mapBoth

Transforms both sides simultaneously.
import { Either } from "effect"

const result = Either.mapBoth(Either.right(1), {
  onLeft: (e: string) => `Error: ${e}`,
  onRight: (n: number) => n * 2
})
// Right(2)

Conversions

import { Either, Option } from "effect"

Either.fromOption(Option.some(1), () => 'error')
// Right(1)

Either.fromOption(Option.none(), () => 'error')
// Left('error')

Chaining Operations

flatMap

import { Either } from "effect"

const result = Either.right(2).pipe(
  Either.flatMap(n => 
    n > 0 ? Either.right(n * 2) : Either.left("Must be positive")
  )
)
// Right(4)

orElse

import { Either } from "effect"

const result = Either.left("error").pipe(
  Either.orElse(() => Either.right(42))
)
// Right(42)

Error Handling

catchAll

import { Either } from "effect"

const result = Either.left("error").pipe(
  Either.catchAll(error => Either.right(`Recovered from: ${error}`))
)
// Right("Recovered from: error")

Combining Eithers

zipWith

import { Either } from "effect"

const result = Either.zipWith(
  Either.right(2),
  Either.right(3),
  (a, b) => a + b
)
// Right(5)

all

import { Either } from "effect"

const result = Either.all([
  Either.right(1),
  Either.right(2),
  Either.right(3)
])
// Right([1, 2, 3])

const withError = Either.all([
  Either.right(1),
  Either.left("error"),
  Either.right(3)
])
// Left("error")
Either is right-biased, meaning operations like map and flatMap operate on the Right value. The Left value typically represents an error and is preserved through transformations.

Use Cases

  • Error handling without exceptions
  • Validation results
  • Parsing operations
  • API responses with success/failure states
  • Railway-oriented programming

Key Operations

OperationDescription
rightCreates a successful Either
leftCreates a failed Either
trySafely executes a function
isRightChecks if Either is Right
isLeftChecks if Either is Left
matchPattern match on Either
mapTransforms the Right value
mapLeftTransforms the Left value
flatMapChains Either-returning operations
fromOptionConverts Option to Either

Build docs developers (and LLMs) love