Skip to content

Introduction

In long-running applications, managing resources efficiently is essential, particularly when building large-scale systems. If resources like socket connections, database connections, or file descriptors are not properly managed, it can lead to resource leaks, which degrade application performance and reliability. Effect provides constructs that help ensure resources are properly managed and released, even in cases where exceptions occur.

By ensuring that every time a resource is acquired, there is a corresponding mechanism to release it, Effect simplifies the process of resource management in your application.

In many programming languages, the try / finally construct ensures that cleanup code runs regardless of whether an operation succeeds or fails. Effect provides similar functionality through Effect.ensuring, Effect.onExit, and Effect.onError.

The Effect.ensuring function guarantees that a finalizer effect runs whether the main effect succeeds, fails, or is interrupted.

This is useful for performing cleanup actions such as closing file handles, logging messages, or releasing locks.

If you need access to the effect’s result, consider using onExit.

Example (Running a Finalizer in All Outcomes)

import {
import Console
Console
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// Define a cleanup effect
const
const handler: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
handler
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const ensuring: <void, never>(finalizer: Effect.Effect<void, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Guarantees the execution of a finalizer when an effect starts execution.

Details

This function allows you to specify a finalizer effect that will always be run once the effect starts execution, regardless of whether the effect succeeds, fails, or is interrupted.

When to Use

This is useful when you need to ensure that certain cleanup or final steps are executed in all cases, such as releasing resources or performing necessary logging.

While this function provides strong guarantees about executing the finalizer, it is considered a low-level tool, which may not be ideal for more complex resource management. For higher-level resource management with automatic acquisition and release, see the

acquireRelease

family of functions. For use cases where you need access to the result of an effect, consider using

onExit

.

Example (Running a Finalizer in All Outcomes)

import { Console, Effect } from "effect"
// Define a cleanup effect
const handler = Effect.ensuring(Console.log("Cleanup completed"))
// Define a successful effect
const success = Console.log("Task completed").pipe(
Effect.as("some result"),
handler
)
Effect.runFork(success)
// Output:
// Task completed
// Cleanup completed
// Define a failing effect
const failure = Console.log("Task failed").pipe(
Effect.andThen(Effect.fail("some error")),
handler
)
Effect.runFork(failure)
// Output:
// Task failed
// Cleanup completed
// Define an interrupted effect
const interruption = Console.log("Task interrupted").pipe(
Effect.andThen(Effect.interrupt),
handler
)
Effect.runFork(interruption)
// Output:
// Task interrupted
// Cleanup completed

@seeonExit for a version that provides access to the result of an effect.

@since2.0.0

ensuring
(
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Cleanup completed"))
// Define a successful effect
const
const success: Effect.Effect<string, never, never>
success
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task completed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>, Effect.Effect<string, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

Replaces the value inside an effect with a constant value.

Details

This function allows you to ignore the original value inside an effect and replace it with a constant value.

When to Use

It is useful when you no longer need the value produced by an effect but want to ensure that the effect completes successfully with a specific constant result instead. For instance, you can replace the value produced by a computation with a predefined value, ignoring what was calculated before.

Example (Replacing a Value)

import { pipe, Effect } from "effect"
// Replaces the value 5 with the constant "new value"
const program = pipe(Effect.succeed(5), Effect.as("new value"))
Effect.runPromise(program).then(console.log)
// Output: "new value"

@since2.0.0

as
("some result"),
const handler: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <string, never>(effect: Effect.Effect<string, never, never>, options?: RunForkOptions) => RuntimeFiber<string, never>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const success: Effect.Effect<string, never, never>
success
)
/*
Output:
Task completed
Cleanup completed
*/
// Define a failing effect
const
const failure: Effect.Effect<never, string, never>
failure
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task failed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, string, never>, Effect.Effect<never, string, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, string, never>>(f: Effect.Effect<never, string, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, string | E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

Example (Creating a Failed Effect)

import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@seesucceed to create an effect that represents a successful value.

@since2.0.0

fail
("some error")),
const handler: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <never, string>(effect: Effect.Effect<never, string, never>, options?: RunForkOptions) => RuntimeFiber<never, string>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const failure: Effect.Effect<never, string, never>
failure
)
/*
Output:
Task failed
Cleanup completed
*/
// Define an interrupted effect
const
const interruption: Effect.Effect<never, never, never>
interruption
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task interrupted").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, never, never>, Effect.Effect<never, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, never, never>>(f: Effect.Effect<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const interrupt: Effect.Effect<never, never, never>

Represents an effect that interrupts the current fiber.

Details

This effect models the explicit interruption of the fiber in which it runs. When executed, it causes the fiber to stop its operation immediately, capturing the interruption details such as the fiber's ID and its start time. The resulting interruption can be observed in the Exit type if the effect is run with functions like

runPromiseExit

.

Example

import { Effect } from "effect"
const program = Effect.gen(function* () {
console.log("start")
yield* Effect.sleep("2 seconds")
yield* Effect.interrupt
console.log("done")
return "some result"
})
Effect.runPromiseExit(program).then(console.log)
// Output:
// start
// {
// _id: 'Exit',
// _tag: 'Failure',
// cause: {
// _id: 'Cause',
// _tag: 'Interrupt',
// fiberId: {
// _id: 'FiberId',
// _tag: 'Runtime',
// id: 0,
// startTimeMillis: ...
// }
// }
// }

@since2.0.0

interrupt
),
const handler: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <never, never>(effect: Effect.Effect<never, never, never>, options?: RunForkOptions) => RuntimeFiber<never, never>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const interruption: Effect.Effect<never, never, never>
interruption
)
/*
Output:
Task interrupted
Cleanup completed
*/

Effect.onExit allows you to run a cleanup effect after the main effect completes, receiving an Exit value that describes the outcome.

  • If the effect succeeds, the Exit holds the success value.
  • If it fails, the Exit includes the error or failure cause.
  • If it is interrupted, the Exit reflects that interruption.

The cleanup step itself is uninterruptible, which can help manage resources in complex or high-concurrency cases.

Example (Running a Cleanup Function with the Effect’s Result)

import {
import Console
Console
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Exit
Exit
} from "effect"
// Define a cleanup effect that logs the result
const
const handler: <R>(self: Effect.Effect<unknown, unknown, R>) => Effect.Effect<unknown, unknown, R>
handler
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const onExit: <unknown, unknown, void, never>(cleanup: (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<void, never, never>) => <R>(self: Effect.Effect<unknown, unknown, R>) => Effect.Effect<unknown, unknown, R> (+1 overload)

Guarantees that a cleanup function runs regardless of whether the effect succeeds, fails, or is interrupted.

Details

This function ensures that a provided cleanup function is executed after the effect completes, regardless of the outcome. The cleanup function is given the Exit value of the effect, which provides detailed information about the result:

  • If the effect succeeds, the Exit contains the success value.
  • If the effect fails, the Exit contains the error or failure cause.
  • If the effect is interrupted, the Exit reflects the interruption.

The cleanup function is guaranteed to run uninterruptibly, ensuring reliable resource management even in complex or high-concurrency scenarios.

Example (Running a Cleanup Function with the Effect’s Result)

import { Console, Effect, Exit } from "effect"
// Define a cleanup effect that logs the result
const handler = Effect.onExit((exit) =>
Console.log(`Cleanup completed: ${Exit.getOrElse(exit, String)}`)
)
// Define a successful effect
const success = Console.log("Task completed").pipe(
Effect.as("some result"),
handler
)
Effect.runFork(success)
// Output:
// Task completed
// Cleanup completed: some result
// Define a failing effect
const failure = Console.log("Task failed").pipe(
Effect.andThen(Effect.fail("some error")),
handler
)
Effect.runFork(failure)
// Output:
// Task failed
// Cleanup completed: Error: some error
// Define an interrupted effect
const interruption = Console.log("Task interrupted").pipe(
Effect.andThen(Effect.interrupt),
handler
)
Effect.runFork(interruption)
// Output:
// Task interrupted
// Cleanup completed: All fibers interrupted without errors.

@since2.0.0

onExit
((
exit: Exit.Exit<unknown, unknown>
exit
) =>
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(`Cleanup completed: ${
import Exit
Exit
.
const getOrElse: <unknown, unknown, string>(self: Exit.Exit<unknown, unknown>, orElse: (cause: Cause<unknown>) => string) => unknown (+1 overload)

Returns the A if specified exit is a Success, otherwise returns the alternate A value computed from the specified function which receives the Cause<E> of the exit Failure.

@since2.0.0

getOrElse
(
exit: Exit.Exit<unknown, unknown>
exit
,
var String: StringConstructor

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
)}`)
)
// Define a successful effect
const
const success: Effect.Effect<unknown, unknown, never>
success
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task completed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>, Effect.Effect<unknown, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

Replaces the value inside an effect with a constant value.

Details

This function allows you to ignore the original value inside an effect and replace it with a constant value.

When to Use

It is useful when you no longer need the value produced by an effect but want to ensure that the effect completes successfully with a specific constant result instead. For instance, you can replace the value produced by a computation with a predefined value, ignoring what was calculated before.

Example (Replacing a Value)

import { pipe, Effect } from "effect"
// Replaces the value 5 with the constant "new value"
const program = pipe(Effect.succeed(5), Effect.as("new value"))
Effect.runPromise(program).then(console.log)
// Output: "new value"

@since2.0.0

as
("some result"),
const handler: <R>(self: Effect.Effect<unknown, unknown, R>) => Effect.Effect<unknown, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <unknown, unknown>(effect: Effect.Effect<unknown, unknown, never>, options?: RunForkOptions) => RuntimeFiber<unknown, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const success: Effect.Effect<unknown, unknown, never>
success
)
/*
Output:
Task completed
Cleanup completed: some result
*/
// Define a failing effect
const
const failure: Effect.Effect<unknown, unknown, never>
failure
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task failed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, string, never>, Effect.Effect<unknown, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, string, never>>(f: Effect.Effect<never, string, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, string | E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

Example (Creating a Failed Effect)

import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@seesucceed to create an effect that represents a successful value.

@since2.0.0

fail
("some error")),
const handler: <R>(self: Effect.Effect<unknown, unknown, R>) => Effect.Effect<unknown, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <unknown, unknown>(effect: Effect.Effect<unknown, unknown, never>, options?: RunForkOptions) => RuntimeFiber<unknown, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const failure: Effect.Effect<unknown, unknown, never>
failure
)
/*
Output:
Task failed
Cleanup completed: Error: some error
*/
// Define an interrupted effect
const
const interruption: Effect.Effect<unknown, unknown, never>
interruption
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task interrupted").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, never, never>, Effect.Effect<unknown, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, never, never>>(f: Effect.Effect<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const interrupt: Effect.Effect<never, never, never>

Represents an effect that interrupts the current fiber.

Details

This effect models the explicit interruption of the fiber in which it runs. When executed, it causes the fiber to stop its operation immediately, capturing the interruption details such as the fiber's ID and its start time. The resulting interruption can be observed in the Exit type if the effect is run with functions like

runPromiseExit

.

Example

import { Effect } from "effect"
const program = Effect.gen(function* () {
console.log("start")
yield* Effect.sleep("2 seconds")
yield* Effect.interrupt
console.log("done")
return "some result"
})
Effect.runPromiseExit(program).then(console.log)
// Output:
// start
// {
// _id: 'Exit',
// _tag: 'Failure',
// cause: {
// _id: 'Cause',
// _tag: 'Interrupt',
// fiberId: {
// _id: 'FiberId',
// _tag: 'Runtime',
// id: 0,
// startTimeMillis: ...
// }
// }
// }

@since2.0.0

interrupt
),
const handler: <R>(self: Effect.Effect<unknown, unknown, R>) => Effect.Effect<unknown, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <unknown, unknown>(effect: Effect.Effect<unknown, unknown, never>, options?: RunForkOptions) => RuntimeFiber<unknown, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const interruption: Effect.Effect<unknown, unknown, never>
interruption
)
/*
Output:
Task interrupted
Cleanup completed: All fibers interrupted without errors.
*/

This function lets you attach a cleanup effect that runs whenever the calling effect fails, passing the cause of the failure to the cleanup effect.

You can use it to perform actions such as logging, releasing resources, or applying additional recovery steps.

The cleanup effect will also run if the failure is caused by interruption, and it is uninterruptible, so it always finishes once it starts.

Example (Running Cleanup Only on Failure)

import {
import Console
Console
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from "effect"
// This handler logs the failure cause when the effect fails
const
const handler: <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>
handler
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const onError: <unknown, void, never>(cleanup: (cause: Cause<unknown>) => Effect.Effect<void, never, never>) => <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R> (+1 overload)

Ensures a cleanup effect runs whenever the calling effect fails, providing the failure cause to the cleanup effect.

Details

This function allows you to attach a cleanup effect that runs whenever the calling effect fails. The cleanup effect receives the cause of the failure, allowing you to perform actions such as logging, releasing resources, or executing additional recovery logic based on the error. The cleanup effect will execute even if the failure is due to interruption.

Importantly, the cleanup effect itself is uninterruptible, ensuring that it completes regardless of external interruptions.

Example (Running Cleanup Only on Failure)

import { Console, Effect } from "effect"
// This handler logs the failure cause when the effect fails
const handler = Effect.onError((cause) =>
Console.log(`Cleanup completed: ${cause}`)
)
// Define a successful effect
const success = Console.log("Task completed").pipe(
Effect.as("some result"),
handler
)
Effect.runFork(success)
// Output:
// Task completed
// Define a failing effect
const failure = Console.log("Task failed").pipe(
Effect.andThen(Effect.fail("some error")),
handler
)
Effect.runFork(failure)
// Output:
// Task failed
// Cleanup completed: Error: some error
// Define a failing effect
const defect = Console.log("Task failed with defect").pipe(
Effect.andThen(Effect.die("Boom!")),
handler
)
Effect.runFork(defect)
// Output:
// Task failed with defect
// Cleanup completed: Error: Boom!
// Define an interrupted effect
const interruption = Console.log("Task interrupted").pipe(
Effect.andThen(Effect.interrupt),
handler
)
Effect.runFork(interruption)
// Output:
// Task interrupted
// Cleanup completed: All fibers interrupted without errors.

@seeensuring for attaching a cleanup effect that runs on both success and failure.

@seeonExit for attaching a cleanup effect that runs on all possible exits.

@since2.0.0

onError
((
cause: Cause<unknown>
cause
) =>
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(`Cleanup completed: ${
cause: Cause<unknown>
cause
}`)
)
// Define a successful effect
const
const success: Effect.Effect<string, unknown, never>
success
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task completed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<string, never, never>, Effect.Effect<string, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const as: <string>(value: string) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<string, E, R> (+1 overload)

Replaces the value inside an effect with a constant value.

Details

This function allows you to ignore the original value inside an effect and replace it with a constant value.

When to Use

It is useful when you no longer need the value produced by an effect but want to ensure that the effect completes successfully with a specific constant result instead. For instance, you can replace the value produced by a computation with a predefined value, ignoring what was calculated before.

Example (Replacing a Value)

import { pipe, Effect } from "effect"
// Replaces the value 5 with the constant "new value"
const program = pipe(Effect.succeed(5), Effect.as("new value"))
Effect.runPromise(program).then(console.log)
// Output: "new value"

@since2.0.0

as
("some result"),
const handler: <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <string, unknown>(effect: Effect.Effect<string, unknown, never>, options?: RunForkOptions) => RuntimeFiber<string, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const success: Effect.Effect<string, unknown, never>
success
)
/*
Output:
Task completed
*/
// Define a failing effect
const
const failure: Effect.Effect<never, unknown, never>
failure
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task failed").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, string, never>, Effect.Effect<never, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, string, never>>(f: Effect.Effect<never, string, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, string | E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fail: <string>(error: string) => Effect.Effect<never, string, never>

Creates an Effect that represents a recoverable error.

When to Use

Use this function to explicitly signal an error in an Effect. The error will keep propagating unless it is handled. You can handle the error with functions like

catchAll

or

catchTag

.

Example (Creating a Failed Effect)

import { Effect } from "effect"
// ┌─── Effect<never, Error, never>
// ▼
const failure = Effect.fail(
new Error("Operation failed due to network error")
)

@seesucceed to create an effect that represents a successful value.

@since2.0.0

fail
("some error")),
const handler: <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <never, unknown>(effect: Effect.Effect<never, unknown, never>, options?: RunForkOptions) => RuntimeFiber<never, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const failure: Effect.Effect<never, unknown, never>
failure
)
/*
Output:
Task failed
Cleanup completed: Error: some error
*/
// Define a failing effect
const
const defect: Effect.Effect<never, unknown, never>
defect
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task failed with defect").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, never, never>, Effect.Effect<never, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, never, never>>(f: Effect.Effect<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const die: (defect: unknown) => Effect.Effect<never>

Creates an effect that terminates a fiber with a specified error.

Details

This function is used to signal a defect, which represents a critical and unexpected error in the code. When invoked, it produces an effect that does not handle the error and instead terminates the fiber.

The error channel of the resulting effect is of type never, indicating that it cannot recover from this failure.

When to Use

Use this function when encountering unexpected conditions in your code that should not be handled as regular errors but instead represent unrecoverable defects.

Example (Terminating on Division by Zero with a Specified Error)

import { Effect } from "effect"
const divide = (a: number, b: number) =>
b === 0
? Effect.die(new Error("Cannot divide by zero"))
: Effect.succeed(a / b)
// ┌─── Effect<number, never, never>
// ▼
const program = divide(1, 0)
Effect.runPromise(program).catch(console.error)
// Output:
// (FiberFailure) Error: Cannot divide by zero
// ...stack trace...

@seedieSync for a variant that throws a specified error, evaluated lazily.

@seedieMessage for a variant that throws a RuntimeException with a message.

@since2.0.0

die
("Boom!")),
const handler: <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <never, unknown>(effect: Effect.Effect<never, unknown, never>, options?: RunForkOptions) => RuntimeFiber<never, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const defect: Effect.Effect<never, unknown, never>
defect
)
/*
Output:
Task failed with defect
Cleanup completed: Error: Boom!
*/
// Define an interrupted effect
const
const interruption: Effect.Effect<never, unknown, never>
interruption
=
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
("Task interrupted").
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<never, never, never>, Effect.Effect<never, unknown, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Effect.Effect<never, never, never>>(f: Effect.Effect<never, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<never, E, R> (+3 overloads)

Chains two actions, where the second action can depend on the result of the first.

Syntax

const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
// or
const transformedEffect = Effect.andThen(myEffect, anotherEffect)
// or
const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))

When to Use

Use andThen when you need to run multiple actions in sequence, with the second action depending on the result of the first. This is useful for combining effects or handling computations that must happen in order.

Details

The second action can be:

  • A constant value (similar to

as

)

  • A function returning a value (similar to

map

)

  • A Promise
  • A function returning a Promise
  • An Effect
  • A function returning an Effect (similar to

flatMap

)

Note: andThen works well with both Option and Either types, treating them as effects.

Example (Applying a Discount Based on Fetched Amount)

import { pipe, Effect } from "effect"
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Using Effect.map and Effect.flatMap
const result1 = pipe(
fetchTransactionAmount,
Effect.map((amount) => amount * 2),
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result1).then(console.log)
// Output: 190
// Using Effect.andThen
const result2 = pipe(
fetchTransactionAmount,
Effect.andThen((amount) => amount * 2),
Effect.andThen((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(result2).then(console.log)
// Output: 190

@since2.0.0

andThen
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const interrupt: Effect.Effect<never, never, never>

Represents an effect that interrupts the current fiber.

Details

This effect models the explicit interruption of the fiber in which it runs. When executed, it causes the fiber to stop its operation immediately, capturing the interruption details such as the fiber's ID and its start time. The resulting interruption can be observed in the Exit type if the effect is run with functions like

runPromiseExit

.

Example

import { Effect } from "effect"
const program = Effect.gen(function* () {
console.log("start")
yield* Effect.sleep("2 seconds")
yield* Effect.interrupt
console.log("done")
return "some result"
})
Effect.runPromiseExit(program).then(console.log)
// Output:
// start
// {
// _id: 'Exit',
// _tag: 'Failure',
// cause: {
// _id: 'Cause',
// _tag: 'Interrupt',
// fiberId: {
// _id: 'FiberId',
// _tag: 'Runtime',
// id: 0,
// startTimeMillis: ...
// }
// }
// }

@since2.0.0

interrupt
),
const handler: <A, R>(self: Effect.Effect<A, unknown, R>) => Effect.Effect<A, unknown, R>
handler
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runFork: <never, unknown>(effect: Effect.Effect<never, unknown, never>, options?: RunForkOptions) => RuntimeFiber<never, unknown>

Runs an effect in the background, returning a fiber that can be observed or interrupted.

Unless you specifically need a Promise or synchronous operation, runFork is a good default choice.

Details

This function is the foundational way to execute an effect in the background. It creates a "fiber," a lightweight, cooperative thread of execution that can be observed (to access its result), interrupted, or joined. Fibers are useful for concurrent programming and allow effects to run independently of the main program flow.

Once the effect is running in a fiber, you can monitor its progress, cancel it if necessary, or retrieve its result when it completes. If the effect fails, the fiber will propagate the failure, which you can observe and handle.

When to Use

Use this function when you need to run an effect in the background, especially if the effect is long-running or performs periodic tasks. It's suitable for tasks that need to run independently but might still need observation or management, like logging, monitoring, or scheduled tasks.

This function is ideal if you don't need the result immediately or if the effect is part of a larger concurrent workflow.

Example (Running an Effect in the Background)

import { Effect, Console, Schedule, Fiber } from "effect"
// ┌─── Effect<number, never, never>
// ▼
const program = Effect.repeat(
Console.log("running..."),
Schedule.spaced("200 millis")
)
// ┌─── RuntimeFiber<number, never>
// ▼
const fiber = Effect.runFork(program)
setTimeout(() => {
Effect.runFork(Fiber.interrupt(fiber))
}, 500)

@since2.0.0

runFork
(
const interruption: Effect.Effect<never, unknown, never>
interruption
)
/*
Output:
Task interrupted
Cleanup completed: All fibers interrupted without errors.
*/

Many real-world operations involve working with resources that must be released when no longer needed, such as:

  • Database connections
  • File handles
  • Network requests

Effect provides Effect.acquireUseRelease, which ensures that a resource is:

  1. Acquired properly.
  2. Used for its intended purpose.
  3. Released even if an error occurs.

Syntax

Effect.acquireUseRelease(acquire, use, release)

Example (Automatically Managing Resource Lifetime)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Console
Console
} from "effect"
// Define an interface for a resource
interface
interface MyResource
MyResource
{
readonly
MyResource.contents: string
contents
: string
readonly
MyResource.close: () => Promise<void>
close
: () =>
interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<void>
}
// Simulate resource acquisition
const
const getMyResource: () => Promise<MyResource>
getMyResource
= ():
interface Promise<T>

Represents the completion of an asynchronous operation

Promise
<
interface MyResource
MyResource
> =>
var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.
PromiseConstructor.resolve<{
contents: string;
close: () => Promise<void>;
}>(value: {
contents: string;
close: () => Promise<void>;
}): Promise<{
contents: string;
close: () => Promise<void>;
}> (+2 overloads)

Creates a new resolved promise for the provided value.

@paramvalue A promise.

@returnsA promise whose internal state matches the provided promise.

resolve
({
contents: string
contents
: "lorem ipsum",
close: () => Promise<void>
close
: () =>
new
var Promise: PromiseConstructor
new <void>(executor: (resolve: (value: void | PromiseLike<void>) => void, reject: (reason?: any) => void) => void) => Promise<void>

Creates a new Promise.

@paramexecutor A callback used to initialize the promise. This callback is passed two arguments: a resolve callback used to resolve the promise with a value or the result of another promise, and a reject callback used to reject the promise with a provided reason or error.

Promise
((
resolve: (value: void | PromiseLike<void>) => void
resolve
) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
globalThis.Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("Resource released")
resolve: (value: void | PromiseLike<void>) => void
resolve
()
})
})
// Define how the resource is acquired
const
const acquire: Effect.Effect<MyResource, Error, never>
acquire
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tryPromise: <MyResource, Error>(options: {
readonly try: (signal: AbortSignal) => PromiseLike<MyResource>;
readonly catch: (error: unknown) => Error;
}) => Effect.Effect<...> (+1 overload)

Creates an Effect that represents an asynchronous computation that might fail.

When to Use

In situations where you need to perform asynchronous operations that might fail, such as fetching data from an API, you can use the tryPromise constructor. This constructor is designed to handle operations that could throw exceptions by capturing those exceptions and transforming them into manageable errors.

Error Handling

There are two ways to handle errors with tryPromise:

  1. If you don't provide a catch function, the error is caught and the effect fails with an UnknownException.
  2. If you provide a catch function, the error is caught and the catch function maps it to an error of type E.

Interruptions

An optional AbortSignal can be provided to allow for interruption of the wrapped Promise API.

Example (Fetching a TODO Item)

import { Effect } from "effect"
const getTodo = (id: number) =>
// Will catch any errors and propagate them as UnknownException
Effect.tryPromise(() =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
)
// ┌─── Effect<Response, UnknownException, never>
// ▼
const program = getTodo(1)

Example (Custom Error Handling)

import { Effect } from "effect"
const getTodo = (id: number) =>
Effect.tryPromise({
try: () => fetch(`https://jsonplaceholder.typicode.com/todos/${id}`),
// remap the error
catch: (unknown) => new Error(`something went wrong ${unknown}`)
})
// ┌─── Effect<Response, Error, never>
// ▼
const program = getTodo(1)

@seepromise if the effectful computation is asynchronous and does not throw errors.

@since2.0.0

tryPromise
({
try: (signal: AbortSignal) => PromiseLike<MyResource>
try
: () =>
const getMyResource: () => Promise<MyResource>
getMyResource
().
Promise<MyResource>.then<MyResource, never>(onfulfilled?: ((value: MyResource) => MyResource | PromiseLike<MyResource>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<...>) | ... 1 more ... | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
((
res: MyResource
res
) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
globalThis.Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
("Resource acquired")
return
res: MyResource
res
}),
catch: (error: unknown) => Error
catch
: () => new
var Error: ErrorConstructor
new (message?: string) => Error
Error
("getMyResourceError")
})
// Define how the resource is released
const
const release: (res: MyResource) => Effect.Effect<void, never, never>
release
= (
res: MyResource
res
:
interface MyResource
MyResource
) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const promise: <void>(evaluate: (signal: AbortSignal) => PromiseLike<void>) => Effect.Effect<void, never, never>

Creates an Effect that represents an asynchronous computation guaranteed to succeed.

Details

The provided function (thunk) returns a Promise that should never reject; if it does, the error will be treated as a "defect".

This defect is not a standard error but indicates a flaw in the logic that was expected to be error-free. You can think of it similar to an unexpected crash in the program, which can be further managed or logged using tools like

catchAllDefect

.

Interruptions

An optional AbortSignal can be provided to allow for interruption of the wrapped Promise API.

When to Use

Use this function when you are sure the operation will not reject.

Example (Delayed Message)

import { Effect } from "effect"
const delay = (message: string) =>
Effect.promise<string>(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(message)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const program = delay("Async operation completed successfully!")

@seetryPromise for a version that can handle failures.

@since2.0.0

promise
(() =>
res: MyResource
res
.
MyResource.close: () => Promise<void>
close
())
const
const use: (res: MyResource) => Effect.Effect<void, never, never>
use
= (
res: MyResource
res
:
interface MyResource
MyResource
) =>
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(`content is ${
res: MyResource
res
.
MyResource.contents: string
contents
}`)
// ┌─── Effect<void, Error, never>
// ▼
const
const program: Effect.Effect<void, Error, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const acquireUseRelease: <MyResource, Error, never, void, never, never, void, never>(acquire: Effect.Effect<MyResource, Error, never>, use: (a: MyResource) => Effect.Effect<...>, release: (a: MyResource, exit: Exit<...>) => Effect.Effect<...>) => Effect.Effect<...> (+1 overload)

Many real-world operations involve working with resources that must be released when no longer needed, such as:

  • Database connections
  • File handles
  • Network requests

This function ensures that a resource is:

  1. Acquired properly.
  2. Used for its intended purpose.
  3. Released even if an error occurs.

Example (Automatically Managing Resource Lifetime)

import { Effect, Console } from "effect"
// Define an interface for a resource
interface MyResource {
readonly contents: string
readonly close: () => Promise<void>
}
// Simulate resource acquisition
const getMyResource = (): Promise<MyResource> =>
Promise.resolve({
contents: "lorem ipsum",
close: () =>
new Promise((resolve) => {
console.log("Resource released")
resolve()
})
})
// Define how the resource is acquired
const acquire = Effect.tryPromise({
try: () =>
getMyResource().then((res) => {
console.log("Resource acquired")
return res
}),
catch: () => new Error("getMyResourceError")
})
// Define how the resource is released
const release = (res: MyResource) => Effect.promise(() => res.close())
const use = (res: MyResource) => Console.log(`content is ${res.contents}`)
// ┌─── Effect<void, Error, never>
// ▼
const program = Effect.acquireUseRelease(acquire, use, release)
Effect.runPromise(program)
// Output:
// Resource acquired
// content is lorem ipsum
// Resource released

@since2.0.0

acquireUseRelease
(
const acquire: Effect.Effect<MyResource, Error, never>
acquire
,
const use: (res: MyResource) => Effect.Effect<void, never, never>
use
,
const release: (res: MyResource) => Effect.Effect<void, never, never>
release
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const runPromise: <void, Error>(effect: Effect.Effect<void, Error, never>, options?: {
readonly signal?: AbortSignal;
} | undefined) => Promise<void>

Executes an effect and returns the result as a Promise.

Details

This function runs an effect and converts its result into a Promise. If the effect succeeds, the Promise will resolve with the successful result. If the effect fails, the Promise will reject with an error, which includes the failure details of the effect.

The optional options parameter allows you to pass an AbortSignal for cancellation, enabling more fine-grained control over asynchronous tasks.

When to Use

Use this function when you need to execute an effect and work with its result in a promise-based system, such as when integrating with third-party libraries that expect Promise results.

Example (Running a Successful Effect as a Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

Example (Handling a Failing Effect as a Rejected Promise)

import { Effect } from "effect"
Effect.runPromise(Effect.fail("my error")).catch(console.error)
// Output:
// (FiberFailure) Error: my error

@seerunPromiseExit for a version that returns an Exit type instead of rejecting.

@since2.0.0

runPromise
(
const program: Effect.Effect<void, Error, never>
program
)
/*
Output:
Resource acquired
content is lorem ipsum
Resource released
*/