The Exit module describes the result of executing an Effect workflow. An Exit<A, E> can be either a Success with value A or a Failure with a Cause<E>.
Type
type Exit<A, E = never> = Success<A, E> | Failure<A, E>
Represents the result of executing an Effect.
E
type parameter
default:"never"
The error type
Variants
Success
Represents a successful Effect execution.
interface Success<out A, out E> {
readonly _tag: "Success"
readonly value: A
}
Failure
Represents a failed Effect execution.
interface Failure<out A, out E> {
readonly _tag: "Failure"
readonly cause: Cause.Cause<E>
}
Constructors
succeed
Constructs a new Exit.Success.
const succeed: <A>(value: A) => Exit<A>
An Exit representing success
import { Exit } from "effect"
const result = Exit.succeed(42)
fail
Constructs a new Exit.Failure from a recoverable error.
const fail: <E>(error: E) => Exit<never, E>
An Exit representing failure
import { Exit } from "effect"
const result = Exit.fail("Something went wrong")
die
Constructs a new Exit.Failure from an unrecoverable defect.
const die: (defect: unknown) => Exit<never>
An Exit representing a defect
import { Exit } from "effect"
const result = Exit.die(new Error("Unexpected error"))
failCause
Constructs a new Exit.Failure from a Cause.
const failCause: <E>(cause: Cause.Cause<E>) => Exit<never, E>
An Exit with the specified cause
interrupt
Constructs a new Exit.Failure indicating interruption.
const interrupt: (fiberId: FiberId.FiberId) => Exit<never>
The ID of the interrupted fiber
An Exit representing interruption
void
Represents an Exit which succeeds with undefined.
An Exit succeeding with void
Refinements
isExit
Checks if a value is an Exit.
const isExit: (u: unknown) => u is Exit<unknown, unknown>
true if the value is an Exit
isSuccess
Checks if an Exit is a Success.
const isSuccess: <A, E>(self: Exit<A, E>) => self is Success<A, E>
true if the Exit is a Success
import { Exit } from "effect"
const result = Exit.succeed(42)
Exit.isSuccess(result) // true
isFailure
Checks if an Exit is a Failure.
const isFailure: <A, E>(self: Exit<A, E>) => self is Failure<A, E>
isInterrupted
Checks if an Exit is a Failure due to interruption.
const isInterrupted: <A, E>(self: Exit<A, E>) => boolean
Getters
causeOption
Returns the Cause if the Exit is a Failure, None otherwise.
const causeOption: <A, E>(self: Exit<A, E>) => Option.Option<Cause.Cause<E>>
return
Option.Option<Cause.Cause<E>>
Some(cause) for Failure, None for Success
import { Exit, Option } from "effect"
const failure = Exit.fail("error")
const cause = Exit.causeOption(failure)
// Option.some(Cause.fail("error"))
getOrElse
Returns the success value or computes an alternate value.
const getOrElse: {
<E, A2>(orElse: (cause: Cause.Cause<E>) => A2): <A>(self: Exit<A, E>) => A2 | A
<A, E, A2>(self: Exit<A, E>, orElse: (cause: Cause.Cause<E>) => A2): A | A2
}
orElse
(cause: Cause.Cause<E>) => A2
required
Function to compute fallback value
The success value or the computed fallback
import { Exit, Cause } from "effect"
const result = Exit.fail("error")
const value = Exit.getOrElse(result, (cause) => "fallback")
// "fallback"
Mapping
map
Maps over the success value.
const map: {
<A, B>(f: (a: A) => B): <E>(self: Exit<A, E>) => Exit<B, E>
<A, E, B>(self: Exit<A, E>, f: (a: A) => B): Exit<B, E>
}
The transformation function
An Exit with the transformed success value
import { Exit } from "effect"
const result = Exit.succeed(5)
const mapped = Exit.map(result, (n) => n * 2)
// Exit.succeed(10)
mapError
Maps over the error value.
const mapError: {
<E, E2>(f: (e: E) => E2): <A>(self: Exit<A, E>) => Exit<A, E2>
<A, E, E2>(self: Exit<A, E>, f: (e: E) => E2): Exit<A, E2>
}
mapErrorCause
Maps over the Cause.
const mapErrorCause: {
<E, E2>(f: (cause: Cause.Cause<E>) => Cause.Cause<E2>): <A>(self: Exit<A, E>) => Exit<A, E2>
<E, A, E2>(self: Exit<A, E>, f: (cause: Cause.Cause<E>) => Cause.Cause<E2>): Exit<A, E2>
}
mapBoth
Maps over both success and failure.
const mapBoth: {
<E, A, E2, A2>(options: {
readonly onFailure: (e: E) => E2
readonly onSuccess: (a: A) => A2
}): (self: Exit<A, E>) => Exit<A2, E2>
<A, E, E2, A2>(self: Exit<A, E>, options: {
readonly onFailure: (e: E) => E2
readonly onSuccess: (a: A) => A2
}): Exit<A2, E2>
}
Matching
match
Pattern matches on an Exit.
const match: {
<E, A, Z1, Z2>(options: {
readonly onFailure: (cause: Cause.Cause<E>) => Z1
readonly onSuccess: (a: A) => Z2
}): (self: Exit<A, E>) => Z1 | Z2
<A, E, Z1, Z2>(self: Exit<A, E>, options: {
readonly onFailure: (cause: Cause.Cause<E>) => Z1
readonly onSuccess: (a: A) => Z2
}): Z1 | Z2
}
options.onFailure
(cause: Cause.Cause<E>) => Z1
required
Handler for Failure case
The result of the appropriate handler
import { Exit } from "effect"
const result = Exit.succeed(42)
const message = Exit.match(result, {
onSuccess: (value) => `Success: ${value}`,
onFailure: (cause) => `Failure: ${cause}`
})
// "Success: 42"
matchEffect
Pattern matches with effectful handlers.
const matchEffect: {
<E, A2, E2, R, A, A3, E3, R2>(options: {
readonly onFailure: (cause: Cause.Cause<E>) => Effect.Effect<A2, E2, R>
readonly onSuccess: (a: A) => Effect.Effect<A3, E3, R2>
}): (self: Exit<A, E>) => Effect.Effect<A2 | A3, E2 | E3, R | R2>
...
}
Sequencing
flatMap
Sequentially composes Exits.
const flatMap: {
<A, A2, E2>(f: (a: A) => Exit<A2, E2>): <E>(self: Exit<A, E>) => Exit<A2, E2 | E>
<A, E, E2, A2>(self: Exit<A, E>, f: (a: A) => Exit<A2, E2>): Exit<A2, E | E2>
}
flatten
Flattens a nested Exit.
const flatten: <A, E, E2>(self: Exit<Exit<A, E>, E2>) => Exit<A, E | E2>
Zipping
zip
Sequentially zips two Exits.
const zip: {
<A2, E2>(that: Exit<A2, E2>): <A, E>(self: Exit<A, E>) => Exit<[A, A2], E2 | E>
<A, E, A2, E2>(self: Exit<A, E>, that: Exit<A2, E2>): Exit<[A, A2], E | E2>
}
An Exit with a tuple of both values, or the first failure
import { Exit } from "effect"
const exit1 = Exit.succeed(1)
const exit2 = Exit.succeed("hello")
const zipped = Exit.zip(exit1, exit2)
// Exit.succeed([1, "hello"])
zipPar
Parallelly zips two Exits.
const zipPar: {
<A2, E2>(that: Exit<A2, E2>): <A, E>(self: Exit<A, E>) => Exit<[A, A2], E2 | E>
<A, E, A2, E2>(self: Exit<A, E>, that: Exit<A2, E2>): Exit<[A, A2], E | E2>
}
The difference between zip and zipPar is how they combine errors - zipPar combines failures in parallel.
Conversions
fromEither
Converts an Either into an Exit.
const fromEither: <R, L>(either: Either.Either<R, L>) => Exit<R, L>
either
Either.Either<R, L>
required
The Either to convert
fromOption
Converts an Option into an Exit.
const fromOption: <A>(option: Option.Option<A>) => Exit<A, void>