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

Effect overview

Added in v2.0.0


Table of contents


Caching

cached

Returns an effect that lazily computes a result and caches it for subsequent evaluations.

Details

This function wraps an effect and ensures that its result is computed only once. Once the result is computed, it is cached, meaning that subsequent evaluations of the same effect will return the cached result without re-executing the logic.

When to Use

Use this function when you have an expensive or time-consuming operation that you want to avoid repeating. The first evaluation will compute the result, and all following evaluations will immediately return the cached value, improving performance and reducing unnecessary work.

Signature

export declare const cached: <A, E, R>(self: Effect<A, E, R>) => Effect<Effect<A, E, R>>

Example

import { Effect, Console } from "effect"

let i = 1
const expensiveTask = Effect.promise<string>(() => {
  console.log("expensive task...")
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`result ${i++}`)
    }, 100)
  })
})

const program = Effect.gen(function* () {
  console.log("non-cached version:")
  yield* expensiveTask.pipe(Effect.andThen(Console.log))
  yield* expensiveTask.pipe(Effect.andThen(Console.log))
  console.log("cached version:")
  const cached = yield* Effect.cached(expensiveTask)
  yield* cached.pipe(Effect.andThen(Console.log))
  yield* cached.pipe(Effect.andThen(Console.log))
})

// Effect.runFork(program)
// Output:
// non-cached version:
// expensive task...
// result 1
// expensive task...
// result 2
// cached version:
// expensive task...
// result 3
// result 3

Added in v2.0.0

cachedFunction

Returns a memoized version of a function with effects, reusing results for the same inputs.

Details

This function creates a memoized version of a given function that performs an effect. Memoization ensures that once a result is computed for a specific input, it is stored and reused for subsequent calls with the same input, reducing the need to recompute the result.

The function can optionally take an Equivalence parameter to determine how inputs are compared for caching purposes.

When to Use

Use this function when you have a function that performs an effect and you want to avoid recomputing the result for the same input multiple times.

It’s ideal for functions that produce deterministic results based on their inputs, and you want to improve performance by caching the output.

This is particularly useful in scenarios where the function involves expensive calculations or operations that should be avoided after the first execution with the same parameters.

Signature

export declare const cachedFunction: <A, B, E, R>(
  f: (a: A) => Effect<B, E, R>,
  eq?: Equivalence<A>
) => Effect<(a: A) => Effect<B, E, R>>

Example

import { Effect, Random } from "effect"

const program = Effect.gen(function* () {
  const randomNumber = (n: number) => Random.nextIntBetween(1, n)
  console.log("non-memoized version:")
  console.log(yield* randomNumber(10))
  console.log(yield* randomNumber(10))

  console.log("memoized version:")
  const memoized = yield* Effect.cachedFunction(randomNumber)
  console.log(yield* memoized(10))
  console.log(yield* memoized(10))
})

// Effect.runFork(program)
// Example Output:
// non-memoized version:
// 2
// 8
// memoized version:
// 5
// 5

Added in v2.0.0

cachedInvalidateWithTTL

Caches an effect’s result for a specified duration and allows manual invalidation before expiration.

Details

This function behaves similarly to {@link cachedWithTTL} by caching the result of an effect for a specified period of time. However, it introduces an additional feature: it provides an effect that allows you to manually invalidate the cached result before it naturally expires.

This gives you more control over the cache, allowing you to refresh the result when needed, even if the original cache has not yet expired.

Once the cache is invalidated, the next time the effect is evaluated, the result will be recomputed, and the cache will be refreshed.

When to Use

Use this function when you have an effect whose result needs to be cached for a certain period, but you also want the option to refresh the cache manually before the expiration time.

This is useful when you need to ensure that the cached data remains valid for a certain period but still want to invalidate it if the underlying data changes or if you want to force a recomputation.

Signature

export declare const cachedInvalidateWithTTL: {
  (
    timeToLive: Duration.DurationInput
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<[Effect<A, E>, Effect<void>], never, R>
  <A, E, R>(self: Effect<A, E, R>, timeToLive: Duration.DurationInput): Effect<[Effect<A, E>, Effect<void>], never, R>
}

Example

import { Effect, Console } from "effect"

let i = 1
const expensiveTask = Effect.promise<string>(() => {
  console.log("expensive task...")
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`result ${i++}`)
    }, 100)
  })
})

const program = Effect.gen(function* () {
  const [cached, invalidate] = yield* Effect.cachedInvalidateWithTTL(expensiveTask, "1 hour")
  yield* cached.pipe(Effect.andThen(Console.log))
  yield* cached.pipe(Effect.andThen(Console.log))
  yield* invalidate
  yield* cached.pipe(Effect.andThen(Console.log))
})

// Effect.runFork(program)
// Output:
// expensive task...
// result 1
// result 1
// expensive task...
// result 2

Added in v2.0.0

cachedWithTTL

Returns an effect that caches its result for a specified Duration, known as “timeToLive” (TTL).

Details

This function is used to cache the result of an effect for a specified amount of time. This means that the first time the effect is evaluated, its result is computed and stored.

If the effect is evaluated again within the specified timeToLive, the cached result will be used, avoiding recomputation.

After the specified duration has passed, the cache expires, and the effect will be recomputed upon the next evaluation.

When to Use

Use this function when you have an effect that involves costly operations or computations, and you want to avoid repeating them within a short time frame.

It’s ideal for scenarios where the result of an effect doesn’t change frequently and can be reused for a specified duration.

By caching the result, you can improve efficiency and reduce unnecessary computations, especially in performance-critical applications.

Signature

export declare const cachedWithTTL: {
  (timeToLive: Duration.DurationInput): <A, E, R>(self: Effect<A, E, R>) => Effect<Effect<A, E>, never, R>
  <A, E, R>(self: Effect<A, E, R>, timeToLive: Duration.DurationInput): Effect<Effect<A, E>, never, R>
}

Example

import { Effect, Console } from "effect"

let i = 1
const expensiveTask = Effect.promise<string>(() => {
  console.log("expensive task...")
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`result ${i++}`)
    }, 100)
  })
})

const program = Effect.gen(function* () {
  const cached = yield* Effect.cachedWithTTL(expensiveTask, "150 millis")
  yield* cached.pipe(Effect.andThen(Console.log))
  yield* cached.pipe(Effect.andThen(Console.log))
  yield* Effect.sleep("100 millis")
  yield* cached.pipe(Effect.andThen(Console.log))
})

// Effect.runFork(program)
// Output:
// expensive task...
// result 1
// result 1
// expensive task...
// result 2

Added in v2.0.0

once

Returns an effect that executes only once, regardless of how many times it’s called.

Details

This function ensures that a specific effect is executed only a single time, no matter how many times it is invoked. The result of the effect will be cached, and subsequent calls to the effect will immediately return the cached result without re-executing the original logic.

When to Use

Use this function when you need to perform a task only once, regardless of how many times the effect is triggered. It’s particularly useful when you have initialization tasks, logging, or other one-time actions that should not be repeated. This can help optimize performance and avoid redundant actions.

Signature

export declare const once: <A, E, R>(self: Effect<A, E, R>) => Effect<Effect<void, E, R>>

Example

import { Effect, Console } from "effect"

const program = Effect.gen(function* () {
  const task1 = Console.log("task1")
  yield* Effect.repeatN(task1, 2)
  const task2 = yield* Effect.once(Console.log("task2"))
  yield* Effect.repeatN(task2, 2)
})

// Effect.runFork(program)
// Output:
// task1
// task1
// task1
// task2

Added in v2.0.0

Clock

clock

Retrieves the Clock service from the context.

Signature

export declare const clock: Effect<Clock.Clock, never, never>

Example

import { Effect } from "effect"

const program = Effect.gen(function* () {
  const clock = yield* Effect.clock
  const currentTime = yield* clock.currentTimeMillis
  console.log(`Current time in milliseconds: ${currentTime}`)
})

// Effect.runFork(program)
// Example Output:
// Current time in milliseconds: 1735484796134

Added in v2.0.0

clockWith

Retrieves the Clock service from the context and provides it to the specified effectful function.

Signature

export declare const clockWith: <A, E, R>(f: (clock: Clock.Clock) => Effect<A, E, R>) => Effect<A, E, R>

Example

import { Console, Effect } from "effect"

const program = Effect.clockWith((clock) =>
  clock.currentTimeMillis.pipe(
    Effect.map((currentTime) => `Current time is: ${currentTime}`),
    Effect.tap(Console.log)
  )
)

// Effect.runFork(program)
// Example Output:
// Current time is: 1735484929744

Added in v2.0.0

withClock

Executes the specified workflow with the specified implementation of the Clock service.

Signature

export declare const withClock: {
  <C extends Clock.Clock>(clock: C): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
  <C extends Clock.Clock, A, E, R>(effect: Effect<A, E, R>, clock: C): Effect<A, E, R>
}

Added in v2.0.0

withClockScoped

Sets the implementation of the Clock service to the specified value and restores it to its original value when the scope is closed.

Signature

export declare const withClockScoped: <C extends Clock.Clock>(clock: C) => Effect<void, never, Scope.Scope>

Added in v2.0.0

Collecting

all

Combines multiple effects into one, returning results based on the input structure.

Details

Use this function when you need to run multiple effects and combine their results into a single output. It supports tuples, iterables, structs, and records, making it flexible for different input types.

For instance, if the input is a tuple:

//         ┌─── a tuple of effects
//         ▼
Effect.all([effect1, effect2, ...])

the effects are executed sequentially, and the result is a new effect containing the results as a tuple. The results in the tuple match the order of the effects passed to Effect.all.

Concurrency

You can control the execution order (e.g., sequential vs. concurrent) using the concurrency option.

Short-Circuiting Behavior

This function stops execution on the first error it encounters, this is called “short-circuiting”. If any effect in the collection fails, the remaining effects will not run, and the error will be propagated. To change this behavior, you can use the mode option, which allows all effects to run and collect results as Either or Option.

The mode option

The { mode: "either" } option changes the behavior of Effect.all to ensure all effects run, even if some fail. Instead of stopping on the first failure, this mode collects both successes and failures, returning an array of Either instances where each result is either a Right (success) or a Left (failure).

Similarly, the { mode: "validate" } option uses Option to indicate success or failure. Each effect returns None for success and Some with the error for failure.

Signature

export declare const all: <
  const Arg extends Iterable<Effect<any, any, any>> | Record<string, Effect<any, any, any>>,
  O extends {
    readonly concurrency?: Concurrency | undefined
    readonly batching?: boolean | "inherit" | undefined
    readonly discard?: boolean | undefined
    readonly mode?: "default" | "validate" | "either" | undefined
    readonly concurrentFinalizers?: boolean | undefined
  }
>(
  arg: Arg,
  options?: O
) => All.Return<Arg, O>

Example

// Title: Combining Effects in Tuples
import { Effect, Console } from "effect"

const tupleOfEffects = [
  Effect.succeed(42).pipe(Effect.tap(Console.log)),
  Effect.succeed("Hello").pipe(Effect.tap(Console.log))
] as const

//      ┌─── Effect<[number, string], never, never>
//      ▼
const resultsAsTuple = Effect.all(tupleOfEffects)

// Effect.runPromise(resultsAsTuple).then(console.log)
// Output:
// 42
// Hello
// [ 42, 'Hello' ]

Example

// Title: Combining Effects in Iterables
import { Effect, Console } from "effect"

const iterableOfEffects: Iterable<Effect.Effect<number>> = [1, 2, 3].map((n) =>
  Effect.succeed(n).pipe(Effect.tap(Console.log))
)

//      ┌─── Effect<number[], never, never>
//      ▼
const resultsAsArray = Effect.all(iterableOfEffects)

// Effect.runPromise(resultsAsArray).then(console.log)
// Output:
// 1
// 2
// 3
// [ 1, 2, 3 ]

Example

// Title: Combining Effects in Structs
import { Effect, Console } from "effect"

const structOfEffects = {
  a: Effect.succeed(42).pipe(Effect.tap(Console.log)),
  b: Effect.succeed("Hello").pipe(Effect.tap(Console.log))
}

//      ┌─── Effect<{ a: number; b: string; }, never, never>
//      ▼
const resultsAsStruct = Effect.all(structOfEffects)

// Effect.runPromise(resultsAsStruct).then(console.log)
// Output:
// 42
// Hello
// { a: 42, b: 'Hello' }

Example

// Title: Combining Effects in Records
import { Effect, Console } from "effect"

const recordOfEffects: Record<string, Effect.Effect<number>> = {
  key1: Effect.succeed(1).pipe(Effect.tap(Console.log)),
  key2: Effect.succeed(2).pipe(Effect.tap(Console.log))
}

//      ┌─── Effect<{ [x: string]: number; }, never, never>
//      ▼
const resultsAsRecord = Effect.all(recordOfEffects)

// Effect.runPromise(resultsAsRecord).then(console.log)
// Output:
// 1
// 2
// { key1: 1, key2: 2 }

Example

// Title: Short-Circuiting Behavior
import { Effect, Console } from "effect"

const program = Effect.all([
  Effect.succeed("Task1").pipe(Effect.tap(Console.log)),
  Effect.fail("Task2: Oh no!").pipe(Effect.tap(Console.log)),
  // Won't execute due to earlier failure
  Effect.succeed("Task3").pipe(Effect.tap(Console.log))
])

// Effect.runPromiseExit(program).then(console.log)
// Output:
// Task1
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: { _id: 'Cause', _tag: 'Fail', failure: 'Task2: Oh no!' }
// }

Example

// Title: Collecting Results with `mode: "either"`
import { Effect, Console } from "effect"

const effects = [
  Effect.succeed("Task1").pipe(Effect.tap(Console.log)),
  Effect.fail("Task2: Oh no!").pipe(Effect.tap(Console.log)),
  Effect.succeed("Task3").pipe(Effect.tap(Console.log))
]

const program = Effect.all(effects, { mode: "either" })

// Effect.runPromiseExit(program).then(console.log)
// Output:
// Task1
// Task3
// {
//   _id: 'Exit',
//   _tag: 'Success',
//   value: [
//     { _id: 'Either', _tag: 'Right', right: 'Task1' },
//     { _id: 'Either', _tag: 'Left', left: 'Task2: Oh no!' },
//     { _id: 'Either', _tag: 'Right', right: 'Task3' }
//   ]
// }

Example

//Example: Collecting Results with `mode: "validate"`
import { Effect, Console } from "effect"

const effects = [
  Effect.succeed("Task1").pipe(Effect.tap(Console.log)),
  Effect.fail("Task2: Oh no!").pipe(Effect.tap(Console.log)),
  Effect.succeed("Task3").pipe(Effect.tap(Console.log))
]

const program = Effect.all(effects, { mode: "validate" })

// Effect.runPromiseExit(program).then((result) => console.log("%o", result))
// Output:
// Task1
// Task3
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Fail',
//     failure: [
//       { _id: 'Option', _tag: 'None' },
//       { _id: 'Option', _tag: 'Some', value: 'Task2: Oh no!' },
//       { _id: 'Option', _tag: 'None' }
//     ]
//   }
// }

Added in v2.0.0

allSuccesses

Evaluates and runs each effect in the iterable, collecting only the successful results while discarding failures.

Details

This function function processes an iterable of effects and runs each one. If an effect is successful, its result is collected; if it fails, the result is discarded. This ensures that only successful outcomes are kept.

Options

The function also allows you to customize how the effects are handled by specifying options such as concurrency, batching, and how finalizers behave. These options provide flexibility in running the effects concurrently or adjusting other execution details.

Signature

export declare const allSuccesses: <X extends Effect<any, any, any>>(
  elements: Iterable<X>,
  options?:
    | {
        readonly concurrency?: Concurrency | undefined
        readonly batching?: boolean | "inherit" | undefined
        readonly concurrentFinalizers?: boolean | undefined
      }
    | undefined
) => Effect<Array<Effect.Success<X>>, never, Effect.Context<X>>

Example

import { Effect } from "effect"

const tasks = [Effect.succeed(1), Effect.fail("Error 1"), Effect.succeed(2), Effect.fail("Error 2")]

const program = Effect.gen(function* () {
  const successfulResults = yield* Effect.allSuccesses(tasks)
  console.log(successfulResults)
})

// Effect.runFork(program)
// Output: [1, 2]

Added in v2.0.0

allWith

A data-last version of {@link all}, designed for use in pipelines.

When to Use

This function enables you to combine multiple effects and customize execution options such as concurrency levels. This version is useful in functional pipelines where you first define your data and then apply operations to it.

Signature

export declare const allWith: <
  O extends {
    readonly concurrency?: Concurrency | undefined
    readonly batching?: boolean | "inherit" | undefined
    readonly discard?: boolean | undefined
    readonly mode?: "default" | "validate" | "either" | undefined
    readonly concurrentFinalizers?: boolean | undefined
  }
>(
  options?: O
) => <const Arg extends Iterable<Effect<any, any, any>> | Record<string, Effect<any, any, any>>>(
  arg: Arg
) => All.Return<Arg, O>

Example

import { Effect, pipe } from "effect"

const task1 = Effect.succeed(1).pipe(Effect.delay("200 millis"), Effect.tap(Effect.log("task1 done")))

const task2 = Effect.succeed("hello").pipe(Effect.delay("100 millis"), Effect.tap(Effect.log("task2 done")))

const program = pipe(
  [task1, task2],
  // Run both effects concurrently using the concurrent option
  Effect.allWith({ concurrency: 2 })
)

// Effect.runPromise(program).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#3 message="task2 done"
// timestamp=... level=INFO fiber=#2 message="task1 done"
// [ 1, 'hello' ]

Added in v2.0.0

dropUntil

Drops elements until the effectful predicate returns true.

Details

This function processes a collection of elements and uses an effectful predicate to determine when to stop dropping elements. It drops elements from the beginning of the collection until the predicate returns true.

The predicate is a function that takes an element and its index in the collection and returns an effect that evaluates to a boolean.

Once the predicate returns true, the remaining elements of the collection are returned.

Note: The first element for which the predicate returns true is also dropped.

When to Use

This function allows you to conditionally skip over a part of the collection based on some criteria defined in the predicate.

Signature

export declare const dropUntil: {
  <A, E, R>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): (elements: Iterable<A>) => Effect<Array<A>, E, R>
  <A, E, R>(elements: Iterable<A>, predicate: (a: A, i: number) => Effect<boolean, E, R>): Effect<Array<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5, 6]
const predicate = (n: number, i: number) => Effect.succeed(n > 3)

const program = Effect.gen(function* () {
  const result = yield* Effect.dropUntil(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: [5, 6]

Added in v2.0.0

dropWhile

Drops elements as long as the predicate returns true.

Details

This function processes a collection of elements and uses a predicate to decide whether to drop an element.

The predicate is a function that takes an element and its index, and it returns an effect that evaluates to a boolean.

As long as the predicate returns true, elements will continue to be dropped from the collection.

Once the predicate returns false, the remaining elements are kept.

When to Use

This function allows you to discard elements from the start of a collection based on a condition, and only keep the rest when the condition no longer holds.

Signature

export declare const dropWhile: {
  <A, E, R>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): (elements: Iterable<A>) => Effect<Array<A>, E, R>
  <A, E, R>(elements: Iterable<A>, predicate: (a: A, i: number) => Effect<boolean, E, R>): Effect<Array<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5, 6]
const predicate = (n: number, i: number) => Effect.succeed(n <= 3)

const program = Effect.gen(function* () {
  const result = yield* Effect.dropWhile(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: [4, 5, 6]

Added in v2.0.0

findFirst

Returns the first element that satisfies the effectful predicate.

Details

This function processes a collection of elements and applies an effectful predicate to each element.

The predicate is a function that takes an element and its index in the collection, and it returns an effect that evaluates to a boolean.

The function stops as soon as it finds the first element for which the predicate returns true and returns that element wrapped in an Option.

If no element satisfies the predicate, the result will be None.

When to Use

This function allows you to efficiently find an element that meets a specific condition, even when the evaluation involves effects like asynchronous operations or side effects.

Signature

export declare const findFirst: {
  <A, E, R>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): (elements: Iterable<A>) => Effect<Option.Option<A>, E, R>
  <A, E, R>(
    elements: Iterable<A>,
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): Effect<Option.Option<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5]
const predicate = (n: number, i: number) => Effect.succeed(n > 3)

const program = Effect.gen(function* () {
  const result = yield* Effect.findFirst(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: { _id: 'Option', _tag: 'Some', value: 4 }

Added in v2.0.0

Returns the first element of the iterable if the collection is non-empty, or fails with the error NoSuchElementException if the collection is empty.

When to Use

This function is useful when you need to retrieve the first item from a collection and want to handle the case where the collection might be empty without causing an unhandled exception.

Signature

export declare const head: <A, E, R>(self: Effect<Iterable<A>, E, R>) => Effect<A, Cause.NoSuchElementException | E, R>

Example

import { Effect } from "effect"

// Simulate an async operation
const fetchNumbers = Effect.succeed([1, 2, 3]).pipe(Effect.delay("100 millis"))

const program = Effect.gen(function* () {
  const firstElement = yield* Effect.head(fetchNumbers)
  console.log(firstElement)
})

// Effect.runFork(program)
// Output: 1

Added in v2.0.0

mergeAll

Merges an Iterable<Effect<A, E, R>> to a single effect.

Details

This function takes an iterable of effects and combines them into a single effect. It does this by iterating over each effect in the collection and applying a function that accumulates results into a “zero” value, which starts with an initial value and is updated with each effect’s success.

The provided function f is called for each element in the iterable, allowing you to specify how to combine the results.

Options

The function also allows you to customize how the effects are handled by specifying options such as concurrency, batching, and how finalizers behave. These options provide flexibility in running the effects concurrently or adjusting other execution details.

Signature

export declare const mergeAll: {
  <Z, Eff extends Effect<any, any, any>>(
    zero: Z,
    f: (z: Z, a: Effect.Success<Eff>, i: number) => Z,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<Eff>) => Effect<Z, Effect.Error<Eff>, Effect.Context<Eff>>
  <Eff extends Effect<any, any, any>, Z>(
    elements: Iterable<Eff>,
    zero: Z,
    f: (z: Z, a: Effect.Success<Eff>, i: number) => Z,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<Z, Effect.Error<Eff>, Effect.Context<Eff>>
}

Example

import { Effect } from "effect"

const numbers = [Effect.succeed(1), Effect.succeed(2), Effect.succeed(3)]
const add = (sum: number, value: number, i: number) => sum + value
const zero = 0

const program = Effect.gen(function* () {
  const total = yield* Effect.mergeAll(numbers, zero, add)
  console.log(total)
})

// Effect.runFork(program)
// Output: 6

Added in v2.0.0

reduce

Reduces an Iterable<A> using an effectual function f, working sequentially from left to right.

Details

This function takes an iterable and applies a function f to each element in the iterable. The function works sequentially, starting with an initial value zero and then combining it with each element in the collection. The provided function f is called for each element in the iterable, allowing you to accumulate a result based on the current value and the element being processed.

When to Use

The function is often used for operations like summing a collection of numbers or combining results from multiple tasks. It ensures that operations are performed one after the other, maintaining the order of the elements.

Signature

export declare const reduce: {
  <Z, A, E, R>(zero: Z, f: (z: Z, a: A, i: number) => Effect<Z, E, R>): (elements: Iterable<A>) => Effect<Z, E, R>
  <A, Z, E, R>(elements: Iterable<A>, zero: Z, f: (z: Z, a: A, i: number) => Effect<Z, E, R>): Effect<Z, E, R>
}

Example

import { Console, Effect } from "effect"

const processOrder = (id: number) =>
  Effect.succeed({ id, price: 100 * id }).pipe(
    Effect.tap(() => Console.log(`Order ${id} processed`)),
    Effect.delay(500 - id * 100)
  )

const program = Effect.reduce([1, 2, 3, 4], 0, (acc, id, i) =>
  processOrder(id).pipe(Effect.map((order) => acc + order.price))
)

// Effect.runPromise(program).then(console.log)
// Output:
// Order 1 processed
// Order 2 processed
// Order 3 processed
// Order 4 processed
// 1000

Added in v2.0.0

reduceEffect

Reduces an Iterable<Effect<A, E, R>> to a single effect.

Details

This function processes a collection of effects and combines them into one single effect. It starts with an initial effect (zero) and applies a function f to each element in the collection.

Options

The function also allows you to customize how the effects are handled by specifying options such as concurrency, batching, and how finalizers behave. These options provide flexibility in running the effects concurrently or adjusting other execution details.

Signature

export declare const reduceEffect: {
  <Z, E, R, Eff extends Effect<any, any, any>>(
    zero: Effect<Z, E, R>,
    f: (z: NoInfer<Z>, a: Effect.Success<Eff>, i: number) => Z,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<Eff>) => Effect<Z, E | Effect.Error<Eff>, R | Effect.Context<Eff>>
  <Eff extends Effect<any, any, any>, Z, E, R>(
    elements: Iterable<Eff>,
    zero: Effect<Z, E, R>,
    f: (z: NoInfer<Z>, a: Effect.Success<Eff>, i: number) => Z,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<Z, E | Effect.Error<Eff>, R | Effect.Context<Eff>>
}

Example

import { Console, Effect } from "effect"

const processOrder = (id: number) =>
  Effect.succeed({ id, price: 100 * id }).pipe(
    Effect.tap(() => Console.log(`Order ${id} processed`)),
    Effect.delay(500 - id * 100)
  )

const program = Effect.reduceEffect(
  [processOrder(1), processOrder(2), processOrder(3), processOrder(4)],
  Effect.succeed(0),
  (acc, order, i) => acc + order.price
)

// Effect.runPromise(program).then(console.log)
// Output:
// Order 1 processed
// Order 2 processed
// Order 3 processed
// Order 4 processed
// 1000

Added in v2.0.0

reduceRight

Reduces an Iterable<A> using an effectual function f, working sequentially from right to left.

Details

This function takes an iterable and applies a function f to each element in the iterable. The function works sequentially, starting with an initial value zero and then combining it with each element in the collection. The provided function f is called for each element in the iterable, allowing you to accumulate a result based on the current value and the element being processed.

When to Use

The function is often used for operations like summing a collection of numbers or combining results from multiple tasks. It ensures that operations are performed one after the other, maintaining the order of the elements.

Signature

export declare const reduceRight: {
  <A, Z, R, E>(zero: Z, f: (a: A, z: Z, i: number) => Effect<Z, E, R>): (elements: Iterable<A>) => Effect<Z, E, R>
  <A, Z, R, E>(elements: Iterable<A>, zero: Z, f: (a: A, z: Z, i: number) => Effect<Z, E, R>): Effect<Z, E, R>
}

Example

import { Console, Effect } from "effect"

const processOrder = (id: number) =>
  Effect.succeed({ id, price: 100 * id }).pipe(
    Effect.tap(() => Console.log(`Order ${id} processed`)),
    Effect.delay(500 - id * 100)
  )

const program = Effect.reduceRight([1, 2, 3, 4], 0, (id, acc, i) =>
  processOrder(id).pipe(Effect.map((order) => acc + order.price))
)

// Effect.runPromise(program).then(console.log)
// Output:
// Order 4 processed
// Order 3 processed
// Order 2 processed
// Order 1 processed
// 1000

Added in v2.0.0

reduceWhile

Reduces an Iterable<A> using an effectual function body, working sequentially from left to right, stopping the process early when the predicate while is not satisfied.

Details

This function processes a collection of elements, applying a function body to reduce them to a single value, starting from the first element. It checks the value of the accumulator against a predicate (while). If at any point the predicate returns false, the reduction stops, and the accumulated result is returned.

When to Use

Use this function when you need to reduce a collection of elements, but only continue the process as long as a certain condition holds true. For example, if you want to sum values in a list but stop as soon as the sum exceeds a certain threshold, you can use this function.

Signature

export declare const reduceWhile: {
  <Z, A, E, R>(
    zero: Z,
    options: { readonly while: Predicate<Z>; readonly body: (s: Z, a: A, i: number) => Effect<Z, E, R> }
  ): (elements: Iterable<A>) => Effect<Z, E, R>
  <A, Z, E, R>(
    elements: Iterable<A>,
    zero: Z,
    options: { readonly while: Predicate<Z>; readonly body: (s: Z, a: A, i: number) => Effect<Z, E, R> }
  ): Effect<Z, E, R>
}

Example

import { Console, Effect } from "effect"

const processOrder = (id: number) =>
  Effect.succeed({ id, price: 100 * id }).pipe(
    Effect.tap(() => Console.log(`Order ${id} processed`)),
    Effect.delay(500 - id * 100)
  )

const program = Effect.reduceWhile([1, 2, 3, 4], 0, {
  body: (acc, id, i) => processOrder(id).pipe(Effect.map((order) => acc + order.price)),
  while: (acc) => acc < 500
})

// Effect.runPromise(program).then(console.log)
// Output:
// Order 1 processed
// Order 2 processed
// Order 3 processed
// 600

Added in v2.0.0

replicateEffect

Performs this effect the specified number of times and collects the results.

Details

This function repeats an effect multiple times and collects the results into an array. You specify how many times to execute the effect, and it runs that many times, either in sequence or concurrently depending on the provided options.

Options

If the discard option is set to true, the intermediate results are not collected, and the final result of the operation is void.

The function also allows you to customize how the effects are handled by specifying options such as concurrency, batching, and how finalizers behave. These options provide flexibility in running the effects concurrently or adjusting other execution details.

Signature

export declare const replicateEffect: {
  (
    n: number,
    options?: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard?: false | undefined
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<Array<A>, E, R>
  (
    n: number,
    options: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard: true
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<void, E, R>
  <A, E, R>(
    self: Effect<A, E, R>,
    n: number,
    options?: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard?: false | undefined
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): Effect<Array<A>, E, R>
  <A, E, R>(
    self: Effect<A, E, R>,
    n: number,
    options: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard: true
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): Effect<void, E, R>
}

Example

import { Console, Effect } from "effect"

let counter = 0

const task = Effect.sync(() => ++counter).pipe(Effect.tap(() => Console.log(`Task completed`)))

const program = Effect.gen(function* () {
  // Replicate the task 3 times and collect the results
  const results = yield* Effect.replicateEffect(task, 3)
  yield* Console.log(`Results: ${results.join(", ")}`)
})

// Effect.runFork(program)
// Output:
// Task completed
// Task completed
// Task completed
// Results: 1, 2, 3

Added in v2.0.0

takeUntil

Takes elements from a collection until the effectful predicate returns true.

Details

This function processes a collection of elements and uses an effectful predicate to decide when to stop taking elements. The elements are taken from the beginning of the collection until the predicate returns true.

The predicate is a function that takes an element and its index in the collection, and returns an effect that resolves to a boolean.

Once the predicate returns true, the remaining elements of the collection are discarded, and the function stops taking more elements.

Note: The first element for which the predicate returns true is also included in the result.

When to Use

Use this function when you want to conditionally take elements from a collection based on a dynamic condition. For example, you may want to collect numbers from a list until a certain threshold is reached, or gather items until a specific condition is met.

Signature

export declare const takeUntil: {
  <A, R, E>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): (elements: Iterable<A>) => Effect<Array<A>, E, R>
  <A, E, R>(
    elements: Iterable<A>,
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): Effect<Array<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5, 6]
const predicate = (n: number, i: number) => Effect.succeed(n > 3)

const program = Effect.gen(function* () {
  const result = yield* Effect.takeUntil(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: [ 1, 2, 3, 4 ]

Added in v2.0.0

takeWhile

Takes elements as long as the predicate returns true.

Details

This function processes a collection of elements and uses a predicate to decide whether to take an element.

The predicate is a function that takes an element and its index, and it returns an effect that evaluates to a boolean.

As long as the predicate returns true, elements will continue to be taken from the collection.

Once the predicate returns false, the remaining elements are discarded.

Signature

export declare const takeWhile: {
  <A, E, R>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): (elements: Iterable<A>) => Effect<Array<A>, E, R>
  <A, E, R>(
    elements: Iterable<A>,
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
  ): Effect<Array<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5, 6]
const predicate = (n: number, i: number) => Effect.succeed(n <= 3)

const program = Effect.gen(function* () {
  const result = yield* Effect.takeWhile(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: [1, 2, 3]

Added in v2.0.0

Condition Checking

every

Determines whether all elements of the iterable satisfy the effectful predicate.

Details

This function checks whether every element in a given collection (an iterable) satisfies a condition defined by an effectful predicate.

The predicate is a function that takes an element and its index, and it returns an effect that evaluates to a boolean.

The function will process each element and return true if all elements satisfy the predicate; otherwise, it returns false.

When to Use

This function is useful when you need to verify that all items in a collection meet certain criteria, even when the evaluation of each item involves effects, such as asynchronous checks or complex computations.

Signature

export declare const every: {
  <A, E, R>(predicate: (a: A, i: number) => Effect<boolean, E, R>): (elements: Iterable<A>) => Effect<boolean, E, R>
  <A, E, R>(elements: Iterable<A>, predicate: (a: A, i: number) => Effect<boolean, E, R>): Effect<boolean, E, R>
}

Example

import { Effect } from "effect"

const numbers = [2, 4, 6, 8]
const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)

const program = Effect.gen(function* () {
  const allEven = yield* Effect.every(numbers, predicate)
  console.log(allEven)
})

// Effect.runFork(program)
// Output: true

Added in v2.0.0

exists

Determines whether any element of the iterable satisfies the effectual predicate.

Details

This function checks whether any element in a given collection (an iterable) satisfies a condition defined by an effectful predicate.

The predicate is a function that takes an element and its index, and it returns an effect that evaluates to a boolean.

The function will process each element, and if any element satisfies the predicate (returns true), the function will immediately return true.

If none of the elements satisfy the condition, it will return false.

When to Use

This function allows you to quickly check for a condition in a collection without having to manually iterate over it.

Signature

export declare const exists: {
  <A, E, R>(
    predicate: (a: A, i: number) => Effect<boolean, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<A>) => Effect<boolean, E, R>
  <A, E, R>(
    elements: Iterable<A>,
    predicate: (a: A, i: number) => Effect<boolean, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<boolean, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4]
const predicate = (n: number, i: number) => Effect.succeed(n > 2)

const program = Effect.gen(function* () {
  const hasLargeNumber = yield* Effect.exists(numbers, predicate)
  console.log(hasLargeNumber)
})

// Effect.runFork(program)
// Output: true

Added in v2.0.0

isFailure

Checks if an effect has failed.

Details

This function evaluates whether an effect has resulted in a failure. It returns a boolean value wrapped in an effect, with true indicating the effect failed and false otherwise.

The resulting effect cannot fail (never in the error channel) but retains the context of the original effect.

Signature

export declare const isFailure: <A, E, R>(self: Effect<A, E, R>) => Effect<boolean, never, R>

Example

import { Effect } from "effect"

const failure = Effect.fail("Uh oh!")

// console.log(Effect.runSync(Effect.isFailure(failure)))
// Output: true

const defect = Effect.dieMessage("BOOM!")

// Effect.runSync(Effect.isFailure(defect))
// throws: BOOM!

Added in v2.0.0

isSuccess

Checks if an effect has succeeded.

Details

This function evaluates whether an effect has resulted in a success. It returns a boolean value wrapped in an effect, with true indicating the effect succeeded and false otherwise.

The resulting effect cannot fail (never in the error channel) but retains the context of the original effect.

Signature

export declare const isSuccess: <A, E, R>(self: Effect<A, E, R>) => Effect<boolean, never, R>

Added in v2.0.0

liftPredicate

Transforms a Predicate function into an Effect returning the input value if the predicate returns true or failing with specified error if the predicate fails

Signature

export declare const liftPredicate: {
  <A, B extends A, E>(refinement: Refinement<NoInfer<A>, B>, orFailWith: (a: NoInfer<A>) => E): (a: A) => Effect<B, E>
  <A, E>(predicate: Predicate<NoInfer<A>>, orFailWith: (a: NoInfer<A>) => E): (a: A) => Effect<A, E>
  <A, E, B extends A>(self: A, refinement: Refinement<A, B>, orFailWith: (a: A) => E): Effect<B, E>
  <A, E>(self: A, predicate: Predicate<NoInfer<A>>, orFailWith: (a: NoInfer<A>) => E): Effect<A, E>
}

Example

import { Effect } from "effect"

const isPositive = (n: number): boolean => n > 0

// succeeds with `1`
Effect.liftPredicate(1, isPositive, (n) => `${n} is not positive`)

// fails with `"0 is not positive"`
Effect.liftPredicate(0, isPositive, (n) => `${n} is not positive`)

Added in v3.4.0

Conditional Operators

if

Executes one of two effects based on a condition evaluated by an effectful predicate.

Use if to run one of two effects depending on whether the predicate effect evaluates to true or false. If the predicate is true, the onTrue effect is executed. If it is false, the onFalse effect is executed instead.

Signature

export declare const if: { <A1, E1, R1, A2, E2, R2>(options: { readonly onTrue: LazyArg<Effect<A1, E1, R1>>; readonly onFalse: LazyArg<Effect<A2, E2, R2>>; }): <E = never, R = never>(self: boolean | Effect<boolean, E, R>) => Effect<A1 | A2, E1 | E2 | E, R1 | R2 | R>; <A1, E1, R1, A2, E2, R2, E = never, R = never>(self: boolean | Effect<boolean, E, R>, options: { readonly onTrue: LazyArg<Effect<A1, E1, R1>>; readonly onFalse: LazyArg<Effect<A2, E2, R2>>; }): Effect<A1 | A2, E1 | E2 | E, R1 | R2 | R>; }

Example

// Title: Simulating a Coin Flip
import { Effect, Random, Console } from "effect"

const flipTheCoin = Effect.if(Random.nextBoolean, {
  onTrue: () => Console.log("Head"), // Runs if the predicate is true
  onFalse: () => Console.log("Tail") // Runs if the predicate is false
})

// Effect.runFork(flipTheCoin)

Added in v2.0.0

unless

Executes an effect only if the condition is false.

Signature

export declare const unless: {
  (condition: LazyArg<boolean>): <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>, E, R>
  <A, E, R>(self: Effect<A, E, R>, condition: LazyArg<boolean>): Effect<Option.Option<A>, E, R>
}

Added in v2.0.0

unlessEffect

Conditionally execute an effect based on the result of another effect.

Signature

export declare const unlessEffect: {
  <E2, R2>(
    condition: Effect<boolean, E2, R2>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>, E2 | E, R2 | R>
  <A, E, R, E2, R2>(self: Effect<A, E, R>, condition: Effect<boolean, E2, R2>): Effect<Option.Option<A>, E | E2, R | R2>
}

Added in v2.0.0

when

Conditionally executes an effect based on a boolean condition.

Details

This function allows you to run an effect only if a given condition evaluates to true. If the condition is true, the effect is executed, and its result is wrapped in an Option.some. If the condition is false, the effect is skipped, and the result is Option.none.

When to Use

This function is useful for scenarios where you need to dynamically decide whether to execute an effect based on runtime logic, while also representing the skipped case explicitly.

Signature

export declare const when: {
  (condition: LazyArg<boolean>): <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>, E, R>
  <A, E, R>(self: Effect<A, E, R>, condition: LazyArg<boolean>): Effect<Option.Option<A>, E, R>
}

Example

// Title: Conditional Effect Execution
import { Effect, Option } from "effect"

const validateWeightOption = (weight: number): Effect.Effect<Option.Option<number>> =>
  // Conditionally execute the effect if the weight is non-negative
  Effect.succeed(weight).pipe(Effect.when(() => weight >= 0))

// Run with a valid weight
// Effect.runPromise(validateWeightOption(100)).then(console.log)
// Output:
// {
//   _id: "Option",
//   _tag: "Some",
//   value: 100
// }

// Run with an invalid weight
// Effect.runPromise(validateWeightOption(-5)).then(console.log)
// Output:
// {
//   _id: "Option",
//   _tag: "None"
// }

Added in v2.0.0

whenEffect

Conditionally executes an effect based on the result of another effect.

Details

This function allows you to run an effect only if a conditional effect evaluating to a boolean resolves to true. If the conditional effect evaluates to true, the specified effect is executed, and its result is wrapped in Option.some. If the conditional effect evaluates to false, the effect is skipped, and the result is Option.none.

When to Use

This function is particularly useful when the decision to execute an effect depends on the result of another effect, such as a random value, a user-provided input, or a network request result.

Signature

export declare const whenEffect: {
  <E, R>(
    condition: Effect<boolean, E, R>
  ): <A, E2, R2>(effect: Effect<A, E2, R2>) => Effect<Option.Option<A>, E | E2, R | R2>
  <A, E2, R2, E, R>(self: Effect<A, E2, R2>, condition: Effect<boolean, E, R>): Effect<Option.Option<A>, E2 | E, R2 | R>
}

Example

// Title: Using an Effect as a Condition
import { Effect, Random } from "effect"

const randomIntOption = Random.nextInt.pipe(Effect.whenEffect(Random.nextBoolean))

console.log(Effect.runSync(randomIntOption))
// Example Output:
// { _id: 'Option', _tag: 'Some', value: 8609104974198840 }

Added in v2.0.0

whenFiberRef

Executes an effect conditionally based on the value of a FiberRef that satisfies a predicate.

Details

This function enables you to execute an effect only when the value of a specified FiberRef meets a certain condition defined by a predicate. If the value satisfies the predicate, the effect is executed, and the result is wrapped in an Option.some. If the predicate is not satisfied, the effect is skipped, and the result is Option.none. In both cases, the current value of the FiberRef is included in the result.

Signature

export declare const whenFiberRef: {
  <S>(
    fiberRef: FiberRef.FiberRef<S>,
    predicate: Predicate<S>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<[S, Option.Option<A>], E, R>
  <A, E, R, S>(
    self: Effect<A, E, R>,
    fiberRef: FiberRef.FiberRef<S>,
    predicate: Predicate<S>
  ): Effect<[S, Option.Option<A>], E, R>
}

Added in v2.0.0

whenRef

Executes an effect conditionally based on the value of a Ref that satisfies a predicate.

Details

This function allows you to execute an effect only when the value of a specified Ref meets a condition defined by a predicate. If the value satisfies the predicate, the effect is executed, and the result is wrapped in an Option.some. If the predicate is not satisfied, the effect is skipped, and the result is Option.none. In both cases, the current value of the Ref is included in the result.

Signature

export declare const whenRef: {
  <S>(ref: Ref.Ref<S>, predicate: Predicate<S>): <A, E, R>(self: Effect<A, E, R>) => Effect<[S, Option.Option<A>], E, R>
  <A, E, R, S>(self: Effect<A, E, R>, ref: Ref.Ref<S>, predicate: Predicate<S>): Effect<[S, Option.Option<A>], E, R>
}

Added in v2.0.0

Config

configProviderWith

Allows working with the default configuration provider.

Details

This function retrieves the default configuration provider and passes it to the provided function, which can use it to perform computations or retrieve configuration values. The function can return an effect that leverages the configuration provider for its operations.

Signature

export declare const configProviderWith: <A, E, R>(f: (provider: ConfigProvider) => Effect<A, E, R>) => Effect<A, E, R>

Added in v2.0.0

withConfigProvider

Executes an effect using a specific configuration provider.

Details

This function lets you run an effect with a specified configuration provider. The custom provider will override the default configuration provider for the duration of the effect’s execution.

When to Use

This is particularly useful when you need to use a different set of configuration values or sources for specific parts of your application.

Signature

export declare const withConfigProvider: {
  (provider: ConfigProvider): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R>(self: Effect<A, E, R>, provider: ConfigProvider): Effect<A, E, R>
}

Example

import { Config, ConfigProvider, Effect } from "effect"

const customProvider: ConfigProvider.ConfigProvider = ConfigProvider.fromMap(new Map([["custom-key", "custom-value"]]))

const program = Effect.withConfigProvider(customProvider)(
  Effect.gen(function* () {
    const value = yield* Config.string("custom-key")
    console.log(`Config value: ${value}`)
  })
)

// Effect.runPromise(program)
// Output:
// Config value: custom-value

Added in v2.0.0

withConfigProviderScoped

Sets a configuration provider within a scope.

Details

This function sets the configuration provider to a specified value and ensures that it is restored to its original value when the scope is closed.

Signature

export declare const withConfigProviderScoped: (provider: ConfigProvider) => Effect<void, never, Scope.Scope>

Added in v2.0.0

Console

console

Retreives the Console service from the context

Signature

export declare const console: Effect<Console, never, never>

Added in v2.0.0

consoleWith

Retreives the Console service from the context and provides it to the specified effectful function.

Signature

export declare const consoleWith: <A, E, R>(f: (console: Console) => Effect<A, E, R>) => Effect<A, E, R>

Added in v2.0.0

withConsole

Executes the specified workflow with the specified implementation of the console service.

Signature

export declare const withConsole: {
  <C extends Console>(console: C): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R, C extends Console>(effect: Effect<A, E, R>, console: C): Effect<A, E, R>
}

Added in v2.0.0

Context

Service

Simplifies the creation and management of services in Effect by defining both a Tag and a Layer.

Details

This function allows you to streamline the creation of services by combining the definition of a Context.Tag and a Layer in a single step. It supports various ways of providing the service implementation:

  • Using an effect to define the service dynamically.
  • Using sync or succeed to define the service statically.
  • Using scoped to create services with lifecycle management.

It also allows you to specify dependencies for the service, which will be provided automatically when the service is used. Accessors can be optionally generated for the service, making it more convenient to use.

Signature

export declare const Service: <Self = never>() => [Self] extends [never]
  ? MissingSelfGeneric
  : {
      <
        const Key extends string,
        const Make extends
          | {
              readonly scoped: Effect<Service.AllowedType<Key, Make>, any, any>
              readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
              readonly accessors?: boolean
              readonly ಠ_ಠ: never
            }
          | {
              readonly effect: Effect<Service.AllowedType<Key, Make>, any, any>
              readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
              readonly accessors?: boolean
              readonly ಠ_ಠ: never
            }
          | {
              readonly sync: LazyArg<Service.AllowedType<Key, Make>>
              readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
              readonly accessors?: boolean
              readonly ಠ_ಠ: never
            }
          | {
              readonly succeed: Service.AllowedType<Key, Make>
              readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
              readonly accessors?: boolean
              readonly ಠ_ಠ: never
            }
      >(
        key: Key,
        make: Make
      ): Service.Class<Self, Key, Make>
      <
        const Key extends string,
        const Make extends NoExcessProperties<
          {
            readonly scoped: Effect<Service.AllowedType<Key, Make>, any, any>
            readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
            readonly accessors?: boolean
          },
          Make
        >
      >(
        key: Key,
        make: Make
      ): Service.Class<Self, Key, Make>
      <
        const Key extends string,
        const Make extends NoExcessProperties<
          {
            readonly effect: Effect<Service.AllowedType<Key, Make>, any, any>
            readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
            readonly accessors?: boolean
          },
          Make
        >
      >(
        key: Key,
        make: Make
      ): Service.Class<Self, Key, Make>
      <
        const Key extends string,
        const Make extends NoExcessProperties<
          {
            readonly sync: LazyArg<Service.AllowedType<Key, Make>>
            readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
            readonly accessors?: boolean
          },
          Make
        >
      >(
        key: Key,
        make: Make
      ): Service.Class<Self, Key, Make>
      <
        const Key extends string,
        const Make extends NoExcessProperties<
          {
            readonly succeed: Service.AllowedType<Key, Make>
            readonly dependencies?: ReadonlyArray<Layer.Layer.Any>
            readonly accessors?: boolean
          },
          Make
        >
      >(
        key: Key,
        make: Make
      ): Service.Class<Self, Key, Make>
    }

Example

import { Effect } from "effect"

class Prefix extends Effect.Service<Prefix>()("Prefix", {
  sync: () => ({ prefix: "PRE" })
}) {}

class Logger extends Effect.Service<Logger>()("Logger", {
  accessors: true,
  effect: Effect.gen(function* () {
    const { prefix } = yield* Prefix
    return {
      info: (message: string) =>
        Effect.sync(() => {
          console.log(`[${prefix}][${message}]`)
        })
    }
  }),
  dependencies: [Prefix.Default]
}) {}

Added in v3.9.0

Service (namespace)

Added in v3.9.0

ProhibitedType (interface)

Signature

export interface ProhibitedType {
  Service?: `property "Service" is forbidden`
  Identifier?: `property "Identifier" is forbidden`
  Default?: `property "Default" is forbidden`
  DefaultWithoutDependencies?: `property "DefaultWithoutDependencies" is forbidden`
  _op_layer?: `property "_op_layer" is forbidden`
  _op?: `property "_op" is forbidden`
  of?: `property "of" is forbidden`
  make?: `property "make" is forbidden`
  context?: `property "context" is forbidden`
  key?: `property "key" is forbidden`
  stack?: `property "stack" is forbidden`
  name?: `property "name" is forbidden`
  pipe?: `property "pipe" is forbidden`
  use?: `property "use" is forbidden`
  _tag?: `property "_tag" is forbidden`
}

Added in v3.9.0

AllowedType (type alias)

Signature

export type AllowedType<Key extends string, Make> =
  MakeAccessors<Make> extends true
    ? Record<PropertyKey, any> & {
        readonly [K in Extract<keyof MakeService<Make>, keyof ProhibitedType>]: K extends "_tag"
          ? Key
          : ProhibitedType[K]
      }
    : Record<PropertyKey, any> & { readonly _tag?: Key }

Added in v3.9.0

Class (type alias)

Signature

export type Class<Self, Key extends string, Make> = {
  new (_: MakeService<Make>): MakeService<Make> & {
    readonly _tag: Key
  }
  readonly use: <X>(
    body: (_: Self) => X
  ) => [X] extends [Effect<infer A, infer E, infer R>]
    ? Effect<A, E, R | Self>
    : [X] extends [PromiseLike<infer A>]
      ? Effect<A, Cause.UnknownException, Self>
      : Effect<X, never, Self>
  readonly make: (_: MakeService<Make>) => Self
} & Context.Tag<Self, Self> & { key: Key } & (MakeAccessors<Make> extends true
    ? Tag.Proxy<Self, MakeService<Make>>
    : {}) &
  (MakeDeps<Make> extends never
    ? {
        readonly Default: Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
      }
    : {
        readonly DefaultWithoutDependencies: Layer.Layer<Self, MakeError<Make>, MakeContext<Make>>
        readonly Default: Layer.Layer<
          Self,
          MakeError<Make> | MakeDepsE<Make>,
          Exclude<MakeContext<Make>, MakeDepsOut<Make>> | MakeDepsIn<Make>
        >
      })

Added in v3.9.0

MakeAccessors (type alias)

Signature

export type MakeAccessors<Make> = Make extends { readonly accessors: true } ? true : false

Added in v3.9.0

MakeContext (type alias)

Signature

export type MakeContext<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> }
  ? _R
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> }
    ? Exclude<_R, Scope.Scope>
    : never

Added in v3.9.0

MakeDeps (type alias)

Signature

export type MakeDeps<Make> = Make extends { readonly dependencies: ReadonlyArray<Layer.Layer.Any> }
  ? Make["dependencies"][number]
  : never

Added in v3.9.0

MakeDepsE (type alias)

Signature

export type MakeDepsE<Make> = Covariant.Type<MakeDeps<Make>[Layer.LayerTypeId]["_E"]>

Added in v3.9.0

MakeDepsIn (type alias)

Signature

export type MakeDepsIn<Make> = Covariant.Type<MakeDeps<Make>[Layer.LayerTypeId]["_RIn"]>

Added in v3.9.0

MakeDepsOut (type alias)

Signature

export type MakeDepsOut<Make> = Contravariant.Type<MakeDeps<Make>[Layer.LayerTypeId]["_ROut"]>

Added in v3.9.0

MakeError (type alias)

Signature

export type MakeError<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> }
  ? _E
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> }
    ? _E
    : never

Added in v3.9.0

MakeService (type alias)

Signature

export type MakeService<Make> = Make extends { readonly effect: Effect<infer _A, infer _E, infer _R> }
  ? _A
  : Make extends { readonly scoped: Effect<infer _A, infer _E, infer _R> }
    ? _A
    : Make extends { readonly sync: LazyArg<infer A> }
      ? A
      : Make extends { readonly succeed: infer A }
        ? A
        : never

Added in v3.9.0

Tag

Creates a unique tag for a dependency, embedding the service’s methods as static properties.

Details

This function allows you to define a Tag for a service or dependency in your application. The Tag not only acts as an identifier but also provides direct access to the service’s methods via static properties. This makes it easier to access and use the service in your code without manually managing contexts.

In the example below, the fields of the service (in this case, the notify method) are turned into static properties of the Notifications class, making it easier to access them.

Signature

export declare const Tag: <const Id extends string>(
  id: Id
) => <Self, Type extends Tag.AllowedType>() => Context.TagClass<Self, Id, Type> &
  (Type extends Record<PropertyKey, any> ? Tag.Proxy<Self, Type> : {}) & {
    use: <X>(
      body: (_: Type) => X
    ) => [X] extends [Effect<infer A, infer E, infer R>]
      ? Effect<A, E, R | Self>
      : [X] extends [PromiseLike<infer A>]
        ? Effect<A, Cause.UnknownException, Self>
        : Effect<X, never, Self>
  }

Example

import { Effect } from "effect"

class Notifications extends Effect.Tag("Notifications")<
  Notifications,
  { readonly notify: (message: string) => Effect.Effect<void> }
>() {}

// Create an effect that depends on the Notifications service
const action = Notifications.notify("Hello, world!")

Added in v2.0.0

context

Accesses the full context of the effect.

Details

This function provides the ability to access the entire context required by an effect. The context is a container that holds dependencies or environment values needed by an effect to run. By using this function, you can retrieve and work with the context directly within an effect.

Signature

export declare const context: <R>() => Effect<Context.Context<R>, never, R>

Added in v2.0.0

contextWith

Accesses the context and applies a transformation function.

Details

This function retrieves the context of the effect and applies a pure transformation function to it. The result of the transformation is then returned within the effect.

Signature

export declare const contextWith: <R, A>(f: (context: Context.Context<R>) => A) => Effect<A, never, R>

Added in v2.0.0

contextWithEffect

Accesses the context and performs an effectful transformation.

Details

This function retrieves the context and allows you to transform it effectually using another effect. It is useful when the transformation involves asynchronous or effectful operations.

Signature

export declare const contextWithEffect: <R2, A, E, R>(
  f: (context: Context.Context<R2>) => Effect<A, E, R>
) => Effect<A, E, R | R2>

Added in v2.0.0

mapInputContext

Provides part of the required context while leaving the rest unchanged.

Details

This function allows you to transform the context required by an effect, providing part of the context and leaving the rest to be fulfilled later.

Signature

export declare const mapInputContext: {
  <R2, R>(f: (context: Context.Context<R2>) => Context.Context<R>): <A, E>(self: Effect<A, E, R>) => Effect<A, E, R2>
  <A, E, R, R2>(self: Effect<A, E, R>, f: (context: Context.Context<R2>) => Context.Context<R>): Effect<A, E, R2>
}

Example

import { Context, Effect } from "effect"

class Service1 extends Context.Tag("Service1")<Service1, { readonly port: number }>() {}
class Service2 extends Context.Tag("Service2")<Service2, { readonly connection: string }>() {}

const program = Effect.gen(function* () {
  const service1 = yield* Service1
  console.log(service1.port)
  const service2 = yield* Service2
  console.log(service2.connection)
  return "some result"
})

//      ┌─── Effect<string, never, Service2>
//      ▼
const programWithService1 = Effect.mapInputContext(program, (ctx: Context.Context<Service2>) =>
  Context.add(ctx, Service1, { port: 3000 })
)

const runnable = programWithService1.pipe(
  Effect.provideService(Service2, { connection: "localhost" }),
  Effect.provideService(Service1, { port: 3001 })
)

Effect.runPromise(runnable)
// Output:
// 3000
// localhost

Added in v2.0.0

provide

Provides necessary dependencies to an effect, removing its environmental requirements.

Details

This function allows you to supply the required environment for an effect. The environment can be provided in the form of one or more Layers, a Context, a Runtime, or a ManagedRuntime. Once the environment is provided, the effect can run without requiring external dependencies.

You can compose layers to create a modular and reusable way of setting up the environment for effects. For example, layers can be used to configure databases, logging services, or any other required dependencies.

Signature

export declare const provide: {
  <const Layers extends [Layer.Layer.Any, ...Array<Layer.Layer.Any>]>(
    layers: Layers
  ): <A, E, R>(
    self: Effect<A, E, R>
  ) => Effect<
    A,
    E | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
    | { [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number]
    | Exclude<R, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>
  >
  <ROut, E2, RIn>(
    layer: Layer.Layer<ROut, E2, RIn>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E | E2, RIn | Exclude<R, ROut>>
  <R2>(context: Context.Context<R2>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, R2>>
  <R2>(runtime: Runtime.Runtime<R2>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, R2>>
  <E2, R2>(
    managedRuntime: ManagedRuntime.ManagedRuntime<R2, E2>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E | E2, Exclude<R, R2>>
  <A, E, R, const Layers extends [Layer.Layer.Any, ...Array<Layer.Layer.Any>]>(
    self: Effect<A, E, R>,
    layers: Layers
  ): Effect<
    A,
    E | { [k in keyof Layers]: Layer.Layer.Error<Layers[k]> }[number],
    | { [k in keyof Layers]: Layer.Layer.Context<Layers[k]> }[number]
    | Exclude<R, { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]>
  >
  <A, E, R, ROut, E2, RIn>(
    self: Effect<A, E, R>,
    layer: Layer.Layer<ROut, E2, RIn>
  ): Effect<A, E | E2, RIn | Exclude<R, ROut>>
  <A, E, R, R2>(self: Effect<A, E, R>, context: Context.Context<R2>): Effect<A, E, Exclude<R, R2>>
  <A, E, R, R2>(self: Effect<A, E, R>, runtime: Runtime.Runtime<R2>): Effect<A, E, Exclude<R, R2>>
  <A, E, E2, R, R2>(
    self: Effect<A, E, R>,
    runtime: ManagedRuntime.ManagedRuntime<R2, E2>
  ): Effect<A, E | E2, Exclude<R, R2>>
}

Example

import { Context, Effect, Layer } from "effect"

class Database extends Context.Tag("Database")<
  Database,
  { readonly query: (sql: string) => Effect.Effect<Array<unknown>> }
>() {}

const DatabaseLive = Layer.succeed(Database, {
  // Simulate a database query
  query: (sql: string) => Effect.log(`Executing query: ${sql}`).pipe(Effect.as([]))
})

//      ┌─── Effect<unknown[], never, Database>
//      ▼
const program = Effect.gen(function* () {
  const database = yield* Database
  const result = yield* database.query("SELECT * FROM users")
  return result
})

//      ┌─── Effect<unknown[], never, never>
//      ▼
const runnable = Effect.provide(program, DatabaseLive)

// Effect.runPromise(runnable).then(console.log)
// Output:
// timestamp=... level=INFO fiber=#0 message="Executing query: SELECT * FROM users"
// []

Added in v2.0.0

provideService

Provides an implementation for a service in the context of an effect.

Details

This function allows you to supply a specific implementation for a service required by an effect. Services are typically defined using Context.Tag, which acts as a unique identifier for the service. By using this function, you link the service to its concrete implementation, enabling the effect to execute successfully without additional requirements.

For example, you can use this function to provide a random number generator, a logger, or any other service your effect depends on. Once the service is provided, all parts of the effect that rely on the service will automatically use the implementation you supplied.

Signature

export declare const provideService: {
  <I, S>(tag: Context.Tag<I, S>, service: NoInfer<S>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, I>>
  <A, E, R, I, S>(self: Effect<A, E, R>, tag: Context.Tag<I, S>, service: NoInfer<S>): Effect<A, E, Exclude<R, I>>
}

Example

import { Effect, Context } from "effect"

// Declaring a tag for a service that generates random numbers
class Random extends Context.Tag("MyRandomService")<Random, { readonly next: Effect.Effect<number> }>() {}

// Using the service
const program = Effect.gen(function* () {
  const random = yield* Random
  const randomNumber = yield* random.next
  console.log(`random number: ${randomNumber}`)
})

// Providing the implementation
//
//      ┌─── Effect<void, never, never>
//      ▼
const runnable = Effect.provideService(program, Random, {
  next: Effect.sync(() => Math.random())
})

// Run successfully
// Effect.runPromise(runnable)
// Example Output:
// random number: 0.8241872233134417

Added in v2.0.0

provideServiceEffect

Dynamically provides an implementation for a service using an effect.

Details

This function allows you to provide an implementation for a service dynamically by using another effect. The provided effect is executed to produce the service implementation, which is then made available to the consuming effect. This is particularly useful when the service implementation itself requires asynchronous or resource-intensive initialization.

For example, you can use this function to lazily initialize a database connection or fetch configuration values from an external source before making the service available to your effect.

Signature

export declare const provideServiceEffect: {
  <I, S, E1, R1>(
    tag: Context.Tag<I, S>,
    effect: Effect<NoInfer<S>, E1, R1>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E | E1, R1 | Exclude<R, I>>
  <A, E, R, I, S, E1, R1>(
    self: Effect<A, E, R>,
    tag: Context.Tag<I, S>,
    effect: Effect<NoInfer<S>, E1, R1>
  ): Effect<A, E | E1, R1 | Exclude<R, I>>
}

Added in v2.0.0

serviceConstants

Signature

export declare const serviceConstants: <S, SE, SR>(
  getService: Effect<S, SE, SR>
) => {
  [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect<infer A, infer E, infer R>
    ? Effect<A, SE | E, SR | R>
    : Effect<S[k], SE, SR>
}

Added in v2.0.0

serviceFunction

Creates a function that uses a service from the context to produce a value.

Signature

export declare const serviceFunction: <T extends Effect<any, any, any>, Args extends Array<any>, A>(
  getService: T,
  f: (_: Effect.Success<T>) => (...args: Args) => A
) => (...args: Args) => Effect<A, Effect.Error<T>, Effect.Context<T>>

Added in v2.0.0

serviceFunctionEffect

Creates a function that uses a service from the context to produce an effect.

Signature

export declare const serviceFunctionEffect: <T extends Effect<any, any, any>, Args extends Array<any>, A, E, R>(
  getService: T,
  f: (_: Effect.Success<T>) => (...args: Args) => Effect<A, E, R>
) => (...args: Args) => Effect<A, E | Effect.Error<T>, R | Effect.Context<T>>

Added in v2.0.0

serviceFunctions

Signature

export declare const serviceFunctions: <S, SE, SR>(
  getService: Effect<S, SE, SR>
) => {
  [k in keyof S as S[k] extends (...args: Array<any>) => Effect<any, any, any> ? k : never]: S[k] extends (
    ...args: infer Args
  ) => Effect<infer A, infer E, infer R>
    ? (...args: Args) => Effect<A, SE | E, SR | R>
    : never
}

Added in v2.0.0

serviceMembers

Signature

export declare const serviceMembers: <S, SE, SR>(
  getService: Effect<S, SE, SR>
) => {
  functions: {
    [k in keyof S as S[k] extends (...args: Array<any>) => Effect<any, any, any> ? k : never]: S[k] extends (
      ...args: infer Args
    ) => Effect<infer A, infer E, infer R>
      ? (...args: Args) => Effect<A, SE | E, SR | R>
      : never
  }
  constants: {
    [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect<infer A, infer E, infer R>
      ? Effect<A, SE | E, SR | R>
      : Effect<S[k], SE, SR>
  }
}

Added in v2.0.0

serviceOption

Retrieves an optional service from the context as an Option.

Details

This function retrieves a service from the context and wraps it in an Option. If the service is available, it returns a Some containing the service. If the service is not found, it returns a None. This approach is useful when you want to handle the absence of a service gracefully without causing an error.

When to Use

Use this function when:

  • You need to access a service that may or may not be present in the context.
  • You want to handle the absence of a service using the Option type instead of throwing an error.

Signature

export declare const serviceOption: <I, S>(tag: Context.Tag<I, S>) => Effect<Option.Option<S>>

Added in v2.0.0

serviceOptional

Retrieves a service from the context, throwing an error if it is missing.

Details

This function retrieves a required service from the context. If the service is available, it returns the service. If the service is missing, it throws a NoSuchElementException, which can be handled using Effect’s error-handling mechanisms. This is useful for services that are critical to the execution of your effect.

Signature

export declare const serviceOptional: <I, S>(tag: Context.Tag<I, S>) => Effect<S, Cause.NoSuchElementException>

Added in v2.0.0

updateService

Updates a service in the context with a new implementation.

Details

This function modifies the existing implementation of a service in the context. It retrieves the current service, applies the provided transformation function f, and replaces the old service with the transformed one.

When to Use

This is useful for adapting or extending a service’s behavior during the execution of an effect.

Signature

export declare const updateService: {
  <I, S>(
    tag: Context.Tag<I, S>,
    f: (service: NoInfer<S>) => NoInfer<S>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R | I>
  <A, E, R, I, S>(
    self: Effect<A, E, R>,
    tag: Context.Tag<I, S>,
    f: (service: NoInfer<S>) => NoInfer<S>
  ): Effect<A, E, R | I>
}

Added in v2.0.0

Converting Failures to Defects

orDie

Converts an effect’s failure into a fiber termination, removing the error from the effect’s type.

Details

The orDie function is used when you encounter errors that you do not want to handle or recover from. It removes the error type from the effect and ensures that any failure will terminate the fiber. This is useful for propagating failures as defects, signaling that they should not be handled within the effect.

*When to Use

Use orDie when failures should be treated as unrecoverable defects and no error handling is required.

Signature

export declare const orDie: <A, E, R>(self: Effect<A, E, R>) => Effect<A, never, R>

Example

// Title: Propagating an Error as a Defect
import { Effect } from "effect"

const divide = (a: number, b: number) =>
  b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

//      ┌─── Effect<number, never, never>
//      ▼
const program = Effect.orDie(divide(1, 0))

// Effect.runPromise(program).catch(console.error)
// Output:
// (FiberFailure) Error: Cannot divide by zero
//   ...stack trace...

Added in v2.0.0

orDieWith

Converts an effect’s failure into a fiber termination with a custom error.

Details

The orDieWith function behaves like {@link orDie}, but it allows you to provide a mapping function to transform the error before terminating the fiber. This is useful for cases where you want to include a more detailed or user-friendly error when the failure is propagated as a defect.

When to Use

Use orDieWith when failures should terminate the fiber as defects, and you want to customize the error for clarity or debugging purposes.

Signature

export declare const orDieWith: {
  <E>(f: (error: E) => unknown): <A, R>(self: Effect<A, E, R>) => Effect<A, never, R>
  <A, E, R>(self: Effect<A, E, R>, f: (error: E) => unknown): Effect<A, never, R>
}

Example

// Title: Customizing Defect
import { Effect } from "effect"

const divide = (a: number, b: number) =>
  b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

//      ┌─── Effect<number, never, never>
//      ▼
const program = Effect.orDieWith(divide(1, 0), (error) => new Error(`defect: ${error.message}`))

// Effect.runPromise(program).catch(console.error)
// Output:
// (FiberFailure) Error: defect: Cannot divide by zero
//   ...stack trace...

Added in v2.0.0

Creating Effects

async

Creates an Effect from a callback-based asynchronous function.

Details

The resume function:

  • Must be called exactly once. Any additional calls will be ignored.
  • Can return an optional Effect that will be run if the Fiber executing this Effect is interrupted. This can be useful in scenarios where you need to handle resource cleanup if the operation is interrupted.
  • Can receive an AbortSignal to handle interruption if needed.

The FiberId of the fiber that may complete the async callback may also be specified using the blockingOn argument. This is called the “blocking fiber” because it suspends the fiber executing the async effect (i.e. semantically blocks the fiber from making progress). Specifying this fiber id in cases where it is known will improve diagnostics, but not affect the behavior of the returned effect.

When to Use

Use Effect.async when dealing with APIs that use callback-style instead of async/await or Promise.

Signature

export declare const async: <A, E = never, R = never>(
  resume: (callback: (_: Effect<A, E, R>) => void, signal: AbortSignal) => void | Effect<void, never, R>,
  blockingOn?: FiberId.FiberId
) => Effect<A, E, R>

Example

// Title: Wrapping a Callback API
import { Effect } from "effect"
import * as NodeFS from "node:fs"

const readFile = (filename: string) =>
  Effect.async<Buffer, Error>((resume) => {
    NodeFS.readFile(filename, (error, data) => {
      if (error) {
        // Resume with a failed Effect if an error occurs
        resume(Effect.fail(error))
      } else {
        // Resume with a succeeded Effect if successful
        resume(Effect.succeed(data))
      }
    })
  })

//      ┌─── Effect<Buffer, Error, never>
//      ▼
const program = readFile("example.txt")

Example

// Title: Handling Interruption with Cleanup
import { Effect, Fiber } from "effect"
import * as NodeFS from "node:fs"

// Simulates a long-running operation to write to a file
const writeFileWithCleanup = (filename: string, data: string) =>
  Effect.async<void, Error>((resume) => {
    const writeStream = NodeFS.createWriteStream(filename)

    // Start writing data to the file
    writeStream.write(data)

    // When the stream is finished, resume with success
    writeStream.on("finish", () => resume(Effect.void))

    // In case of an error during writing, resume with failure
    writeStream.on("error", (err) => resume(Effect.fail(err)))

    // Handle interruption by returning a cleanup effect
    return Effect.sync(() => {
      console.log(`Cleaning up ${filename}`)
      NodeFS.unlinkSync(filename)
    })
  })

const program = Effect.gen(function* () {
  const fiber = yield* Effect.fork(writeFileWithCleanup("example.txt", "Some long data..."))
  // Simulate interrupting the fiber after 1 second
  yield* Effect.sleep("1 second")
  yield* Fiber.interrupt(fiber) // This will trigger the cleanup
})

// Run the program
// Effect.runPromise(program)
// Output:
// Cleaning up example.txt

Example

// Title: Handling Interruption with AbortSignal
import { Effect, Fiber } from "effect"

// A task that supports interruption using AbortSignal
const interruptibleTask = Effect.async<void, Error>((resume, signal) => {
  // Handle interruption
  signal.addEventListener("abort", () => {
    console.log("Abort signal received")
    clearTimeout(timeoutId)
  })

  // Simulate a long-running task
  const timeoutId = setTimeout(() => {
    console.log("Operation completed")
    resume(Effect.void)
  }, 2000)
})

const program = Effect.gen(function* () {
  const fiber = yield* Effect.fork(interruptibleTask)
  // Simulate interrupting the fiber after 1 second
  yield* Effect.sleep("1 second")
  yield* Fiber.interrupt(fiber)
})

// Run the program
// Effect.runPromise(program)
// Output:
// Abort signal received

Added in v2.0.0

asyncEffect

A variant of {@link async} where the registration function may return an Effect.

Signature

export declare const asyncEffect: <A, E, R, R3, E2, R2>(
  register: (callback: (_: Effect<A, E, R>) => void) => Effect<Effect<void, never, R3> | void, E2, R2>
) => Effect<A, E | E2, R | R2 | R3>

Added in v2.0.0

custom

Low level constructor that enables for custom stack tracing cutpoints.

It is meant to be called with a bag of instructions that become available in the “this” of the effect.

Signature

export declare const custom: {
  <X, A, E, R>(i0: X, body: (this: { effect_instruction_i0: X }) => Effect<A, E, R>): Effect<A, E, R>
  <X, Y, A, E, R>(
    i0: X,
    i1: Y,
    body: (this: { effect_instruction_i0: X; effect_instruction_i1: Y }) => Effect<A, E, R>
  ): Effect<A, E, R>
  <X, Y, Z, A, E, R>(
    i0: X,
    i1: Y,
    i2: Z,
    body: (this: { effect_instruction_i0: X; effect_instruction_i1: Y; effect_instruction_i2: Z }) => Effect<A, E, R>
  ): Effect<A, E, R>
}

Example

import { Effect } from "effect"

const throwingFunction = () => {
  throw new Error()
}
const blowUp = Effect.custom(throwingFunction, function () {
  return Effect.succeed(this.effect_instruction_i0())
})

Added in v2.0.0

die

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.

Signature

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

Example

// Title: 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...

Added in v2.0.0

dieMessage

Creates an effect that terminates a fiber with a RuntimeException containing the specified message.

Details

This function is used to signal a defect, representing a critical and unexpected error in the code. When invoked, it produces an effect that terminates the fiber with a RuntimeException carrying the given message.

The resulting effect has an error channel of type never, indicating it does not handle or recover from the error.

When to Use

Use this function when you want to terminate a fiber due to an unrecoverable defect and include a clear explanation in the message.

Signature

export declare const dieMessage: (message: string) => Effect<never>

Example

// Title: Terminating on Division by Zero with a Specified Message
import { Effect } from "effect"

const divide = (a: number, b: number) => (b === 0 ? Effect.dieMessage("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) RuntimeException: Cannot divide by zero
//   ...stack trace...

Added in v2.0.0

dieSync

Creates an effect that dies with the specified error, evaluated lazily.

Details

This function allows you to create an effect that will terminate with a fatal error. The error is provided as a lazy argument, meaning it will only be evaluated when the effect runs.

Signature

export declare const dieSync: (evaluate: LazyArg<unknown>) => Effect<never>

Added in v2.0.0

fail

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 {@link catchAll} or {@link catchTag}.

Signature

export declare const fail: <E>(error: E) => Effect<never, E>

Example

// Title: Creating a Failed Effect
import { Effect } from "effect"

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

Added in v2.0.0

failCause

Creates an Effect that fails with the specified Cause.

Signature

export declare const failCause: <E>(cause: Cause.Cause<E>) => Effect<never, E>

Added in v2.0.0

failCauseSync

Creates an Effect that fails with the specified Cause, evaluated lazily.

Signature

export declare const failCauseSync: <E>(evaluate: LazyArg<Cause.Cause<E>>) => Effect<never, E>

Added in v2.0.0

failSync

Creates an Effect that fails with the specified error, evaluated lazily.

Signature

export declare const failSync: <E>(evaluate: LazyArg<E>) => Effect<never, E>

Added in v2.0.0

gen

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Signature

export declare const gen: {
  <Eff extends YieldWrap<Effect<any, any, any>>, AEff>(
    f: (resume: Adapter) => Generator<Eff, AEff, never>
  ): Effect<
    AEff,
    [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect<infer _A, infer E, infer _R>>] ? E : never,
    [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect<infer _A, infer _E, infer R>>] ? R : never
  >
  <Self, Eff extends YieldWrap<Effect<any, any, any>>, AEff>(
    self: Self,
    f: (this: Self, resume: Adapter) => Generator<Eff, AEff, never>
  ): Effect<
    AEff,
    [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect<infer _A, infer E, infer _R>>] ? E : never,
    [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect<infer _A, infer _E, infer R>>] ? R : never
  >
}

Example

import { Effect } from "effect"

const addServiceCharge = (amount: number) => amount + 1

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)

const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))

const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))

export const program = Effect.gen(function* () {
  const transactionAmount = yield* fetchTransactionAmount
  const discountRate = yield* fetchDiscountRate
  const discountedAmount = yield* applyDiscount(transactionAmount, discountRate)
  const finalAmount = addServiceCharge(discountedAmount)
  return `Final amount to charge: ${finalAmount}`
})

Added in v2.0.0

never

An effect that that runs indefinitely and never produces any result. The moral equivalent of while(true) {}, only without the wasted CPU cycles.

When to Use

It could be useful for long-running background tasks or to simulate waiting behavior without actually consuming resources. This effect is ideal for cases where you want to keep the program alive or in a certain state without performing any active work.

Signature

export declare const never: Effect<never, never, never>

Added in v2.0.0

promise

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 {@link 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.

Signature

export declare const promise: <A>(evaluate: (signal: AbortSignal) => PromiseLike<A>) => Effect<A>

Example

// Title: 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!")

Added in v2.0.0

succeed

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

Signature

export declare const succeed: <A>(value: A) => Effect<A>

Example

// Title: Creating a Successful Effect
import { Effect } from "effect"

// Creating an effect that represents a successful scenario
//
//      ┌─── Effect<number, never, never>
//      ▼
const success = Effect.succeed(42)

Added in v2.0.0

succeedNone

Returns an effect which succeeds with None.

When to Use

Use this function when you need to represent the absence of a value in your code, especially when working with optional data. This can be helpful when you want to indicate that no result is available without throwing an error or performing additional logic.

Signature

export declare const succeedNone: Effect<Option.Option<never>, never, never>

Added in v2.0.0

succeedSome

Returns an effect which succeeds with the value wrapped in a Some.

Signature

export declare const succeedSome: <A>(value: A) => Effect<Option.Option<A>>

Added in v2.0.0

suspend

Delays the creation of an Effect until it is actually needed.

Details

The Effect.suspend function takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:

  • Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
  • Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
  • Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.

When to Use

Use this function when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.

Signature

export declare const suspend: <A, E, R>(effect: LazyArg<Effect<A, E, R>>) => Effect<A, E, R>

Example

// Title: Lazy Evaluation with Side Effects
import { Effect } from "effect"

let i = 0

const bad = Effect.succeed(i++)

const good = Effect.suspend(() => Effect.succeed(i++))

console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0

console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2

Example

// Title: Recursive Fibonacci
import { Effect } from "effect"

const blowsUp = (n: number): Effect.Effect<number> =>
  n < 2 ? Effect.succeed(1) : Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)

// console.log(Effect.runSync(blowsUp(32)))
// crash: JavaScript heap out of memory

const allGood = (n: number): Effect.Effect<number> =>
  n < 2
    ? Effect.succeed(1)
    : Effect.zipWith(
        Effect.suspend(() => allGood(n - 1)),
        Effect.suspend(() => allGood(n - 2)),
        (a, b) => a + b
      )

console.log(Effect.runSync(allGood(32)))
// Output: 3524578

Example

// Title: Using Effect.suspend to Help TypeScript Infer Types
import { Effect } from "effect"

//   Without suspend, TypeScript may struggle with type inference.
//   Inferred type:
//     (a: number, b: number) =>
//       Effect<never, Error, never> | Effect<number, never, never>
const withoutSuspend = (a: number, b: number) =>
  b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)

//   Using suspend to unify return types.
//   Inferred type:
//     (a: number, b: number) => Effect<number, Error, never>
const withSuspend = (a: number, b: number) =>
  Effect.suspend(() => (b === 0 ? Effect.fail(new Error("Cannot divide by zero")) : Effect.succeed(a / b)))

Added in v2.0.0

sync

Creates an Effect that represents a synchronous side-effectful computation.

Details

The provided function (thunk) must not throw errors; 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 {@link catchAllDefect}.

When to Use

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

Signature

export declare const sync: <A>(thunk: LazyArg<A>) => Effect<A>

Example

// Title: Logging a Message
import { Effect } from "effect"

const log = (message: string) =>
  Effect.sync(() => {
    console.log(message) // side effect
  })

//      ┌─── Effect<void, never, never>
//      ▼
const program = log("Hello, World!")

Added in v2.0.0

try

Creates an Effect that represents a synchronous computation that might fail.

When to Use

In situations where you need to perform synchronous operations that might fail, such as parsing JSON, you can use the try 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 try:

  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.

Signature

export declare const try: { <A, E>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E; }): Effect<A, E>; <A>(thunk: LazyArg<A>): Effect<A, Cause.UnknownException>; }

Example

// Title: Safe JSON Parsing
import { Effect } from "effect"

const parse = (input: string) =>
  // This might throw an error if input is not valid JSON
  Effect.try(() => JSON.parse(input))

//      ┌─── Effect<any, UnknownException, never>
//      ▼
const program = parse("")

Example

// Title: Custom Error Handling
import { Effect } from "effect"

const parse = (input: string) =>
  Effect.try({
    // JSON.parse may throw for bad input
    try: () => JSON.parse(input),
    // remap the error
    catch: (unknown) => new Error(`something went wrong ${unknown}`)
  })

//      ┌─── Effect<any, Error, never>
//      ▼
const program = parse("")

Added in v2.0.0

tryPromise

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.

Signature

export declare const tryPromise: {
  <A, E>(options: {
    readonly try: (signal: AbortSignal) => PromiseLike<A>
    readonly catch: (error: unknown) => E
  }): Effect<A, E>
  <A>(evaluate: (signal: AbortSignal) => PromiseLike<A>): Effect<A, Cause.UnknownException>
}

Example

// Title: 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

// Title: 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)

Added in v2.0.0

void

Represents an effect that does nothing and produces no value.

When to Use

Use this effect when you need to represent an effect that does nothing. This is useful in scenarios where you need to satisfy an effect-based interface or control program flow without performing any operations. For example, it can be used in situations where you want to return an effect from a function but do not need to compute or return any result.

Signature

export declare const void: Effect<void, never, never>

Added in v2.0.0

withConsoleScoped

Sets the implementation of the console service to the specified value and restores it to its original value when the scope is closed.

Signature

export declare const withConsoleScoped: <A extends Console>(console: A) => Effect<void, never, Scope.Scope>

Added in v2.0.0

withFiberRuntime

Signature

export declare const withFiberRuntime: <A, E = never, R = never>(
  withRuntime: (fiber: Fiber.RuntimeFiber<A, E>, status: FiberStatus.Running) => Effect<A, E, R>
) => Effect<A, E, R>

Added in v2.0.0

yieldNow

Signature

export declare const yieldNow: (options?: { readonly priority?: number | undefined }) => Effect<void>

Added in v2.0.0

Delays & Timeouts

delay

Delays the execution of an effect by a specified Duration.

**Details

This function postpones the execution of the provided effect by the specified duration. The duration can be provided in various formats supported by the Duration module.

Internally, this function does not block the thread; instead, it uses an efficient, non-blocking mechanism to introduce the delay.

Signature

export declare const delay: {
  (duration: Duration.DurationInput): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R>(self: Effect<A, E, R>, duration: Duration.DurationInput): Effect<A, E, R>
}

Example

import { Console, Effect } from "effect"

const task = Console.log("Task executed")

const program = Console.log("start").pipe(
  Effect.andThen(
    // Delays the log message by 2 seconds
    task.pipe(Effect.delay("2 seconds"))
  )
)

// Effect.runFork(program)
// Output:
// start
// Task executed

Added in v2.0.0

sleep

Suspends the execution of an effect for a specified Duration.

Details

This function pauses the execution of an effect for a given duration. It is asynchronous, meaning that it does not block the fiber executing the effect. Instead, the fiber is suspended during the delay period and can resume once the specified time has passed.

The duration can be specified using various formats supported by the Duration module, such as a string ("2 seconds") or numeric value representing milliseconds.

Signature

export declare const sleep: (duration: Duration.DurationInput) => Effect<void>

Example

import { Effect } from "effect"

const program = Effect.gen(function* () {
  console.log("Starting task...")
  yield* Effect.sleep("3 seconds") // Waits for 3 seconds
  console.log("Task completed!")
})

// Effect.runFork(program)
// Output:
// Starting task...
// Task completed!

Added in v2.0.0

timed

Executes an effect and measures the time it takes to complete.

Details

This function wraps the provided effect and returns a new effect that, when executed, performs the original effect and calculates its execution duration.

The result of the new effect includes both the execution time (as a Duration) and the original effect’s result. This is useful for monitoring performance or gaining insights into the time taken by specific operations.

The original effect’s behavior (success, failure, or interruption) remains unchanged, and the timing information is provided alongside the result in a tuple.

Signature

export declare const timed: <A, E, R>(self: Effect<A, E, R>) => Effect<[duration: Duration.Duration, result: A], E, R>

Example

import { Duration, Effect } from "effect"

const task = Effect.gen(function* () {
  yield* Effect.sleep("2 seconds") // Simulates some work
  return "some result"
})

const timedTask = task.pipe(Effect.timed)

const program = Effect.gen(function* () {
  const [duration, result] = yield* timedTask
  console.log(`Task completed in ${Duration.toMillis(duration)} ms with result: ${result}`)
})

// Effect.runFork(program)
// Output: Task completed in 2003.749125 ms with result: some result

Added in v2.0.0

timedWith

Executes an effect and measures its execution time using a custom clock.

Details

This function extends the functionality of {@link timed} by allowing you to specify a custom clock for measuring the execution duration. The provided effect (nanoseconds) represents the clock and should return the current time in nanoseconds. The timing information is computed using this custom clock instead of the default system clock.

Signature

export declare const timedWith: {
  <E1, R1>(
    nanoseconds: Effect<bigint, E1, R1>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<[Duration.Duration, A], E1 | E, R1 | R>
  <A, E, R, E1, R1>(
    self: Effect<A, E, R>,
    nanoseconds: Effect<bigint, E1, R1>
  ): Effect<[Duration.Duration, A], E | E1, R | R1>
}

Added in v2.0.0

timeout

Adds a time limit to an effect, triggering a timeout if the effect exceeds the duration.

Details

This function allows you to enforce a time limit on the execution of an effect. If the effect does not complete within the given duration, it fails with a TimeoutException. This is useful for preventing tasks from hanging indefinitely, especially in scenarios where responsiveness or resource limits are critical.

The returned effect will either:

  • Succeed with the original effect’s result if it completes within the specified duration.
  • Fail with a TimeoutException if the time limit is exceeded.

Signature

export declare const timeout: {
  (duration: Duration.DurationInput): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E | Cause.TimeoutException, R>
  <A, E, R>(self: Effect<A, E, R>, duration: Duration.DurationInput): Effect<A, Cause.TimeoutException | E, R>
}

Example

import { Effect } from "effect"

const task = Effect.gen(function* () {
  console.log("Start processing...")
  yield* Effect.sleep("2 seconds") // Simulates a delay in processing
  console.log("Processing complete.")
  return "Result"
})

// Output will show a TimeoutException as the task takes longer
// than the specified timeout duration
const timedEffect = task.pipe(Effect.timeout("1 second"))

// Effect.runPromiseExit(timedEffect).then(console.log)
// Output:
// Start processing...
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Fail',
//     failure: { _tag: 'TimeoutException' }
//   }
// }

Added in v2.0.0

timeoutFail

Specifies a custom error to be produced when a timeout occurs.

Details

This function allows you to handle timeouts in a customized way by defining a specific error to be raised when an effect exceeds the given duration. Unlike default timeout behaviors that use generic exceptions, this function gives you the flexibility to specify a meaningful error type that aligns with your application’s needs.

When you apply this function, you provide:

  • A duration: The time limit for the effect.
  • An onTimeout function: A lazy evaluation function that generates the custom error if the timeout occurs.

If the effect completes within the time limit, its result is returned normally. Otherwise, the onTimeout function is triggered, and its output is used as the error for the effect.

Signature

export declare const timeoutFail: {
  <E1>(options: {
    readonly onTimeout: LazyArg<E1>
    readonly duration: Duration.DurationInput
  }): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E1 | E, R>
  <A, E, R, E1>(
    self: Effect<A, E, R>,
    options: { readonly onTimeout: LazyArg<E1>; readonly duration: Duration.DurationInput }
  ): Effect<A, E | E1, R>
}

Example

import { Effect } from "effect"

const task = Effect.gen(function* () {
  console.log("Start processing...")
  yield* Effect.sleep("2 seconds") // Simulates a delay in processing
  console.log("Processing complete.")
  return "Result"
})

class MyTimeoutError {
  readonly _tag = "MyTimeoutError"
}

const program = task.pipe(
  Effect.timeoutFail({
    duration: "1 second",
    onTimeout: () => new MyTimeoutError() // Custom timeout error
  })
)

// Effect.runPromiseExit(program).then(console.log)
// Output:
// Start processing...
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Fail',
//     failure: MyTimeoutError { _tag: 'MyTimeoutError' }
//   }
// }

Added in v2.0.0

timeoutFailCause

Specifies a custom defect to be thrown when a timeout occurs.

Details

This function allows you to handle timeouts as exceptional cases by generating a custom defect when an effect exceeds the specified duration. You provide:

  • A duration: The time limit for the effect.
  • An onTimeout function: A lazy evaluation function that generates the custom defect (typically created using Cause.die).

If the effect completes within the time limit, its result is returned normally. Otherwise, the custom defect is triggered, and the effect fails with that defect.

When to Use

This is especially useful when you need to treat timeouts as critical failures in your application and wish to include meaningful information in the defect.

Signature

export declare const timeoutFailCause: {
  <E1>(options: {
    readonly onTimeout: LazyArg<Cause.Cause<E1>>
    readonly duration: Duration.DurationInput
  }): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E1 | E, R>
  <A, E, R, E1>(
    self: Effect<A, E, R>,
    options: { readonly onTimeout: LazyArg<Cause.Cause<E1>>; readonly duration: Duration.DurationInput }
  ): Effect<A, E | E1, R>
}

Example

import { Effect, Cause } from "effect"

const task = Effect.gen(function* () {
  console.log("Start processing...")
  yield* Effect.sleep("2 seconds") // Simulates a delay in processing
  console.log("Processing complete.")
  return "Result"
})

const program = task.pipe(
  Effect.timeoutFailCause({
    duration: "1 second",
    onTimeout: () => Cause.die("Timed out!") // Custom defect for timeout
  })
)

// Effect.runPromiseExit(program).then(console.log)
// Output:
// Start processing...
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: { _id: 'Cause', _tag: 'Die', defect: 'Timed out!' }
// }

Added in v2.0.0

timeoutOption

Gracefully handles timeouts by returning an Option that represents either the result or a timeout.

Details

This function wraps the outcome of an effect in an Option type. If the effect completes within the specified duration, it returns a Some containing the result. If the effect times out, it returns a None. Unlike other timeout methods, this approach does not raise errors or exceptions; instead, it allows you to treat timeouts as a regular outcome, simplifying the logic for handling delays.

When to Use

This is useful when you want to handle timeouts without causing the program to fail, making it easier to manage situations where you expect tasks might take too long but want to continue executing other tasks.

Signature

export declare const timeoutOption: {
  (duration: Duration.DurationInput): <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>, E, R>
  <A, E, R>(self: Effect<A, E, R>, duration: Duration.DurationInput): Effect<Option.Option<A>, E, R>
}

Example

import { Effect } from "effect"

const task = Effect.gen(function* () {
  console.log("Start processing...")
  yield* Effect.sleep("2 seconds") // Simulates a delay in processing
  console.log("Processing complete.")
  return "Result"
})

const timedOutEffect = Effect.all([
  task.pipe(Effect.timeoutOption("3 seconds")),
  task.pipe(Effect.timeoutOption("1 second"))
])

// Effect.runPromise(timedOutEffect).then(console.log)
// Output:
// Start processing...
// Processing complete.
// Start processing...
// [
//   { _id: 'Option', _tag: 'Some', value: 'Result' },
//   { _id: 'Option', _tag: 'None' }
// ]

Added in v3.1.0

timeoutTo

Provides custom behavior for successful and timed-out operations.

Details

This function allows you to define distinct outcomes for an effect depending on whether it completes within a specified time frame or exceeds the timeout duration. You can provide:

  • onSuccess: A handler for processing the result of the effect if it completes successfully within the time limit.
  • onTimeout: A handler for generating a result when the effect times out.
  • duration: The maximum allowed time for the effect to complete.

When to Use

Unlike {@link timeout}, which raises an exception for timeouts, this function gives you full control over the behavior for both success and timeout scenarios. It is particularly useful when you want to encapsulate timeouts and successes into a specific data structure, like an Either type, to represent these outcomes in a meaningful way.

Signature

export declare const timeoutTo: {
  <A, B, B1>(options: {
    readonly onTimeout: LazyArg<B1>
    readonly onSuccess: (a: A) => B
    readonly duration: Duration.DurationInput
  }): <E, R>(self: Effect<A, E, R>) => Effect<B | B1, E, R>
  <A, E, R, B1, B>(
    self: Effect<A, E, R>,
    options: {
      readonly onTimeout: LazyArg<B1>
      readonly onSuccess: (a: A) => B
      readonly duration: Duration.DurationInput
    }
  ): Effect<B1 | B, E, R>
}

Example

import { Effect, Either } from "effect"

const task = Effect.gen(function* () {
  console.log("Start processing...")
  yield* Effect.sleep("2 seconds") // Simulates a delay in processing
  console.log("Processing complete.")
  return "Result"
})

const program = task.pipe(
  Effect.timeoutTo({
    duration: "1 second",
    onSuccess: (result): Either.Either<string, string> => Either.right(result),
    onTimeout: (): Either.Either<string, string> => Either.left("Timed out!")
  })
)

// Effect.runPromise(program).then(console.log)
// Output:
// Start processing...
// {
//   _id: "Either",
//   _tag: "Left",
//   left: "Timed out!"
// }

Added in v2.0.0

Do notation

Do

The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind and let.

Here’s how the do simulation works:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Effect 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

Signature

export declare const Do: Effect<{}, never, never>

Example

import { Effect, pipe } from "effect"

const result = pipe(
  Effect.Do,
  Effect.bind("x", () => Effect.succeed(2)),
  Effect.bind("y", () => Effect.succeed(3)),
  Effect.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(Effect.runSync(result), { x: 2, y: 3, sum: 5 })

Added in v2.0.0

bind

The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind and let.

Here’s how the do simulation works:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Effect 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

Signature

export declare const bind: {
  <N extends string, A extends object, B, E2, R2>(
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => Effect<B, E2, R2>
  ): <E1, R1>(self: Effect<A, E1, R1>) => Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E2 | E1, R2 | R1>
  <A extends object, N extends string, E1, R1, B, E2, R2>(
    self: Effect<A, E1, R1>,
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => Effect<B, E2, R2>
  ): Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E1 | E2, R1 | R2>
}

Example

import { Effect, pipe } from "effect"

const result = pipe(
  Effect.Do,
  Effect.bind("x", () => Effect.succeed(2)),
  Effect.bind("y", () => Effect.succeed(3)),
  Effect.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(Effect.runSync(result), { x: 2, y: 3, sum: 5 })

Added in v2.0.0

bindAll

bindAll combines all with bind. It is useful when you want to concurrently run multiple effects and then combine their results in a Do notation pipeline.

Signature

export declare const bindAll: {
  <
    A extends object,
    X extends Record<string, Effect<any, any, any>>,
    O extends {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly mode?: "default" | "validate" | "either" | undefined
      readonly concurrentFinalizers?: boolean | undefined
    }
  >(
    f: (a: NoInfer<A>) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
    options?: undefined | O
  ): <E1, R1>(
    self: Effect<A, E1, R1>
  ) => [All.ReturnObject<X, false, All.ExtractMode<O>>] extends [Effect<infer Success, infer Error, infer Context>]
    ? Effect<
        { [K in keyof A | keyof Success]: K extends keyof A ? A[K] : K extends keyof Success ? Success[K] : never },
        E1 | Error,
        R1 | Context
      >
    : never
  <
    A extends object,
    X extends Record<string, Effect<any, any, any>>,
    O extends {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly mode?: "default" | "validate" | "either" | undefined
      readonly concurrentFinalizers?: boolean | undefined
    },
    E1,
    R1
  >(
    self: Effect<A, E1, R1>,
    f: (a: NoInfer<A>) => [Extract<keyof X, keyof A>] extends [never] ? X : `Duplicate keys`,
    options?:
      | undefined
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly mode?: "default" | "validate" | "either" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
  ): [All.ReturnObject<X, false, All.ExtractMode<O>>] extends [Effect<infer Success, infer Error, infer Context>]
    ? Effect<
        { [K in keyof A | keyof Success]: K extends keyof A ? A[K] : K extends keyof Success ? Success[K] : never },
        E1 | Error,
        R1 | Context
      >
    : never
}

Example

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

const result = pipe(
  Effect.Do,
  Effect.bind("x", () => Effect.succeed(2)),
  Effect.bindAll(
    ({ x }) => ({
      a: Effect.succeed(x),
      b: Effect.fail("oops")
    }),
    { concurrency: 2, mode: "either" }
  )
)
assert.deepStrictEqual(Effect.runSync(result), { x: 2, a: Either.right(2), b: Either.left("oops") })

Added in v3.7.0

bindTo

The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind and let.

Here’s how the do simulation works:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Effect 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

Signature

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

Example

import { Effect, pipe } from "effect"

const result = pipe(
  Effect.Do,
  Effect.bind("x", () => Effect.succeed(2)),
  Effect.bind("y", () => Effect.succeed(3)),
  Effect.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(Effect.runSync(result), { x: 2, y: 3, sum: 5 })

Added in v2.0.0

let

The “do simulation” in Effect allows you to write code in a more declarative style, similar to the “do notation” in other programming languages. It provides a way to define variables and perform operations on them using functions like bind and let.

Here’s how the do simulation works:

  1. Start the do simulation using the Do value
  2. Within the do simulation scope, you can use the bind function to define variables and bind them to Effect 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

Signature

export declare const let: {
  <N extends string, A extends object, B>(
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => B
  ): <E, R>(self: Effect<A, E, R>) => Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
  <A extends object, N extends string, E, R, B>(
    self: Effect<A, E, R>,
    name: Exclude<N, keyof A>,
    f: (a: NoInfer<A>) => B
  ): Effect<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }, E, R>
}

Example

import { Effect, pipe } from "effect"

const result = pipe(
  Effect.Do,
  Effect.bind("x", () => Effect.succeed(2)),
  Effect.bind("y", () => Effect.succeed(3)),
  Effect.let("sum", ({ x, y }) => x + y)
)
assert.deepStrictEqual(Effect.runSync(result), { x: 2, y: 3, sum: 5 })

Added in v2.0.0

Error Accumulation

partition

Processes an iterable and applies an effectful function to each element, categorizing the results into successes and failures.

Details

This function processes each element in the provided iterable by applying an effectful function to it. The results are then categorized into two separate lists: one for failures and another for successes. This separation allows you to handle the two categories differently. Failures are collected in a list without interrupting the processing of the remaining elements, so the operation continues even if some elements fail. This is particularly useful when you need to handle both successful and failed results separately, without stopping the entire process on encountering a failure.

When to Use

Use this function when you want to process a collection of items and handle errors or failures without interrupting the processing of other items. It’s useful when you need to distinguish between successful and failed results and process them separately, for example, when logging errors while continuing to work with valid data. The function ensures that failures are captured, while successes are processed normally.

Signature

export declare const partition: {
  <A, B, E, R>(
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<A>) => Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>
  <A, B, E, R>(
    elements: Iterable<A>,
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>
}

Example

import { Effect } from "effect"

//      ┌─── Effect<[string[], number[]], never, never>
//      ▼
const program = Effect.partition([0, 1, 2, 3, 4], (n) => {
  if (n % 2 === 0) {
    return Effect.succeed(n)
  } else {
    return Effect.fail(`${n} is not even`)
  }
})

// Effect.runPromise(program).then(console.log, console.error)
// Output:
// [ [ '1 is not even', '3 is not even' ], [ 0, 2, 4 ] ]

Added in v2.0.0

validate

Combines multiple effects and accumulates both successes and failures.

Details

This function allows you to combine multiple effects, continuing through all effects even if some of them fail. Unlike other functions that stop execution upon encountering an error, this function collects all errors into a Cause. The final result includes all successes and the accumulated failures.

By default, effects are executed sequentially, but you can control concurrency and batching behavior using the options parameter. This provides flexibility in scenarios where you want to maximize performance or ensure specific ordering.

Signature

export declare const validate: {
  <B, E1, R1>(
    that: Effect<B, E1, R1>,
    options?:
      | {
          readonly concurrent?: boolean | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<[A, B], E1 | E, R1 | R>
  <A, E, R, B, E1, R1>(
    self: Effect<A, E, R>,
    that: Effect<B, E1, R1>,
    options?:
      | {
          readonly concurrent?: boolean | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<[A, B], E | E1, R | R1>
}

Example

import { Effect, Console } from "effect"

const task1 = Console.log("task1").pipe(Effect.as(1))
const task2 = Effect.fail("Oh uh!").pipe(Effect.as(2))
const task3 = Console.log("task2").pipe(Effect.as(3))
const task4 = Effect.fail("Oh no!").pipe(Effect.as(4))

const program = task1.pipe(Effect.validate(task2), Effect.validate(task3), Effect.validate(task4))

// Effect.runPromiseExit(program).then(console.log)
// Output:
// task1
// task2
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Sequential',
//     left: { _id: 'Cause', _tag: 'Fail', failure: 'Oh uh!' },
//     right: { _id: 'Cause', _tag: 'Fail', failure: 'Oh no!' }
//   }
// }

Added in v2.0.0

validateAll

Applies an effectful operation to each element in a collection while collecting both successes and failures.

Details

This function allows you to apply an effectful operation to every item in a collection.

Unlike {@link forEach}, which would stop at the first error, this function continues processing all elements, accumulating both successes and failures.

When to Use

Use this function when you want to process every item in a collection, even if some items fail. This is particularly useful when you need to perform operations on all elements without halting due to an error.

Keep in mind that if there are any failures, all successes will be lost, so this function is not suitable when you need to keep the successful results in case of errors.

Signature

export declare const validateAll: {
  <A, B, E, R>(
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly discard?: false | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<A>) => Effect<Array<B>, RA.NonEmptyArray<E>, R>
  <A, B, E, R>(
    f: (a: A, i: number) => Effect<B, E, R>,
    options: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard: true
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): (elements: Iterable<A>) => Effect<void, RA.NonEmptyArray<E>, R>
  <A, B, E, R>(
    elements: Iterable<A>,
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly discard?: false | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<Array<B>, RA.NonEmptyArray<E>, R>
  <A, B, E, R>(
    elements: Iterable<A>,
    f: (a: A, i: number) => Effect<B, E, R>,
    options: {
      readonly concurrency?: Concurrency | undefined
      readonly batching?: boolean | "inherit" | undefined
      readonly discard: true
      readonly concurrentFinalizers?: boolean | undefined
    }
  ): Effect<void, RA.NonEmptyArray<E>, R>
}

Example

import { Effect, Console } from "effect"

//      ┌─── Effect<number[], [string, ...string[]], never>
//      ▼
const program = Effect.validateAll([1, 2, 3, 4, 5], (n) => {
  if (n < 4) {
    return Console.log(`item ${n}`).pipe(Effect.as(n))
  } else {
    return Effect.fail(`${n} is not less that 4`)
  }
})

// Effect.runPromiseExit(program).then(console.log)
// Output:
// item 1
// item 2
// item 3
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Fail',
//     failure: [ '4 is not less that 4', '5 is not less that 4' ]
//   }
// }

Added in v2.0.0

validateFirst

This function is similar to {@link validateAll} but with a key difference: it returns the first successful result or all errors if none of the operations succeed.

Details

This function processes a collection of elements and applies an effectful operation to each. Unlike {@link validateAll}, which accumulates both successes and failures, Effect.validateFirst stops and returns the first success it encounters. If no success occurs, it returns all accumulated errors. This can be useful when you are interested in the first successful result and want to avoid processing further once a valid result is found.

Signature

export declare const validateFirst: {
  <A, B, E, R>(
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<A>) => Effect<B, Array<E>, R>
  <A, B, E, R>(
    elements: Iterable<A>,
    f: (a: A, i: number) => Effect<B, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<B, Array<E>, R>
}

Example

import { Effect, Console } from "effect"

//      ┌─── Effect<number, string[], never>
//      ▼
const program = Effect.validateFirst([1, 2, 3, 4, 5], (n) => {
  if (n < 4) {
    return Effect.fail(`${n} is not less that 4`)
  } else {
    return Console.log(`item ${n}`).pipe(Effect.as(n))
  }
})

// Effect.runPromise(program).then(console.log, console.error)
// Output:
// item 4
// 4

Added in v2.0.0

validateWith

Sequentially combines two effects using a specified combiner function while accumulating errors.

Details

This function combines two effects, self and that, into a single effect by applying the provided combiner function to their results. If both effects succeed, the combiner function is applied to their results to produce the final value. If either effect fails, the failures are accumulated into a combined Cause.

By default, effects are executed sequentially. However, the execution mode can be controlled using the options parameter to enable concurrency, batching, or customized finalizer behavior.

Signature

export declare const validateWith: {
  <B, E1, R1, A, C>(
    that: Effect<B, E1, R1>,
    f: (a: A, b: B) => C,
    options?:
      | {
          readonly concurrent?: boolean | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): <E, R>(self: Effect<A, E, R>) => Effect<C, E1 | E, R1 | R>
  <A, E, R, B, E1, R1, C>(
    self: Effect<A, E, R>,
    that: Effect<B, E1, R1>,
    f: (a: A, b: B) => C,
    options?:
      | {
          readonly concurrent?: boolean | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<C, E | E1, R | R1>
}

Added in v2.0.0

Error handling

Retry (namespace)

Added in v2.0.0

Options (interface)

Signature

export interface Options<E> {
  while?: ((error: E) => boolean | Effect<boolean, any, any>) | undefined
  until?: ((error: E) => boolean | Effect<boolean, any, any>) | undefined
  times?: number | undefined
  schedule?: Schedule.Schedule<any, E, any> | undefined
}

Added in v2.0.0

Return (type alias)

Signature

export type Return<R, E, A, O extends Options<E>> =
  Effect<
    A,
    | (O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _R> }
        ? E
        : O extends { until: Refinement<E, infer E2> }
          ? E2
          : E)
    | (O extends { while: (...args: Array<any>) => Effect<infer _A, infer E, infer _R> } ? E : never)
    | (O extends { until: (...args: Array<any>) => Effect<infer _A, infer E, infer _R> } ? E : never),
    | R
    | (O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer R> } ? R : never)
    | (O extends { while: (...args: Array<any>) => Effect<infer _A, infer _E, infer R> } ? R : never)
    | (O extends { until: (...args: Array<any>) => Effect<infer _A, infer _E, infer R> } ? R : never)
  > extends infer Z
    ? Z
    : never

Added in v2.0.0

catch

Recovers from a specified error by catching it and handling it with a provided function.

Details

This function allows you to recover from specific errors that occur during the execution of an effect. It works by catching a specific type of error (identified by a discriminator) and then handling it using a provided handler function. The handler can return a new effect that helps recover from the error, allowing the program to continue. If the error doesn’t match the specified type, the function allows the original effect to continue as it was.

Signature

export declare const catch: { <N extends keyof E, K extends E[N] & string, E, A1, E1, R1>(discriminator: N, options: { readonly failure: K; readonly onFailure: (error: Extract<E, { [n in N]: K; }>) => Effect<A1, E1, R1>; }): <A, R>(self: Effect<A, E, R>) => Effect<A1 | A, E1 | Exclude<E, { [n in N]: K; }>, R1 | R>; <A, E, R, N extends keyof E, K extends E[N] & string, A1, E1, R1>(self: Effect<A, E, R>, discriminator: N, options: { readonly failure: K; readonly onFailure: (error: Extract<E, { [n in N]: K; }>) => Effect<A1, E1, R1>; }): Effect<A | A1, E1 | Exclude<E, { [n in N]: K; }>, R | R1>; }

Example

import { Console, Effect } from "effect"

class NetworkError {
  readonly _tag = "NetworkError"
}
class ValidationError {
  readonly _tag = "ValidationError"
}

// Simulate an effect that may fail
const task: Effect.Effect<never, NetworkError | ValidationError, never> = Effect.fail(new NetworkError())

const program = Effect.gen(function* () {
  const result = yield* Effect.catch(task, "_tag", {
    failure: "NetworkError",
    onFailure: (error) => Effect.succeed(`recovered from error: ${error._tag}`)
  })
  console.log(`Result: ${result}`)
})

// Effect.runFork(program)
// Output: Result: recovered from error: NetworkError

Added in v2.0.0

catchAll

Handles all errors in an effect by providing a fallback effect.

Details

This function catches any errors that may occur during the execution of an effect and allows you to handle them by specifying a fallback effect. This ensures that the program continues without failing by recovering from errors using the provided fallback logic.

Note: This function only handles recoverable errors. It will not recover from unrecoverable defects.

Signature

export declare const catchAll: {
  <E, A2, E2, R2>(f: (e: E) => Effect<A2, E2, R2>): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2, R2 | R>
  <A, E, R, A2, E2, R2>(self: Effect<A, E, R>, f: (e: E) => Effect<A2, E2, R2>): Effect<A2 | A, E2, R2 | R>
}

Example

// Title: Providing Recovery Logic for Recoverable Errors
import { Effect, Random } from "effect"

class HttpError {
  readonly _tag = "HttpError"
}

class ValidationError {
  readonly _tag = "ValidationError"
}

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const program = Effect.gen(function* () {
  const n1 = yield* Random.next
  const n2 = yield* Random.next
  if (n1 < 0.5) {
    yield* Effect.fail(new HttpError())
  }
  if (n2 < 0.5) {
    yield* Effect.fail(new ValidationError())
  }
  return "some result"
})

//      ┌─── Effect<string, never, never>
//      ▼
const recovered = program.pipe(Effect.catchAll((error) => Effect.succeed(`Recovering from ${error._tag}`)))

Added in v2.0.0

catchAllCause

Handles both recoverable and unrecoverable errors by providing a recovery effect.

When to Use

The catchAllCause function allows you to handle all errors, including unrecoverable defects, by providing a recovery effect. The recovery logic is based on the Cause of the error, which provides detailed information about the failure.

When to Recover from Defects

Defects are unexpected errors that typically shouldn’t be recovered from, as they often indicate serious issues. However, in some cases, such as dynamically loaded plugins, controlled recovery might be needed.

Signature

export declare const catchAllCause: {
  <E, A2, E2, R2>(
    f: (cause: Cause.Cause<E>) => Effect<A2, E2, R2>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    f: (cause: Cause.Cause<E>) => Effect<A2, E2, R2>
  ): Effect<A | A2, E2, R | R2>
}

Example

// Title: Recovering from All Errors
import { Cause, Effect } from "effect"

// Define an effect that may fail with a recoverable or unrecoverable error
const program = Effect.fail("Something went wrong!")

// Recover from all errors by examining the cause
const recovered = program.pipe(
  Effect.catchAllCause((cause) =>
    Cause.isFailType(cause)
      ? Effect.succeed("Recovered from a regular error")
      : Effect.succeed("Recovered from a defect")
  )
)

// Effect.runPromise(recovered).then(console.log)
// Output: "Recovered from a regular error"

Added in v2.0.0

catchAllDefect

Recovers from all defects using a provided recovery function.

When to Use

There is no sensible way to recover from defects. This method should be used only at the boundary between Effect and an external system, to transmit information on a defect for diagnostic or explanatory purposes.

Details

catchAllDefect allows you to handle defects, which are unexpected errors that usually cause the program to terminate. This function lets you recover from these defects by providing a function that handles the error. However, it does not handle expected errors (like those from {@link fail}) or execution interruptions (like those from {@link interrupt}).

When to Recover from Defects

Defects are unexpected errors that typically shouldn’t be recovered from, as they often indicate serious issues. However, in some cases, such as dynamically loaded plugins, controlled recovery might be needed.

Signature

export declare const catchAllDefect: {
  <A2, E2, R2>(
    f: (defect: unknown) => Effect<A2, E2, R2>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2 | E, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    f: (defect: unknown) => Effect<A2, E2, R2>
  ): Effect<A | A2, E | E2, R | R2>
}

Example

// Title: Handling All Defects
import { Effect, Cause, Console } from "effect"

// Simulating a runtime error
const task = Effect.dieMessage("Boom!")

const program = Effect.catchAllDefect(task, (defect) => {
  if (Cause.isRuntimeException(defect)) {
    return Console.log(`RuntimeException defect caught: ${defect.message}`)
  }
  return Console.log("Unknown defect caught.")
})

// We get an Exit.Success because we caught all defects
// Effect.runPromiseExit(program).then(console.log)
// Output:
// RuntimeException defect caught: Boom!
// {
//   _id: "Exit",
//   _tag: "Success",
//   value: undefined
// }

Added in v2.0.0

catchIf

Recovers from specific errors based on a predicate.

When to Use

catchIf works similarly to {@link catchSome}, but it allows you to recover from errors by providing a predicate function. If the predicate matches the error, the recovery effect is applied. This function doesn’t alter the error type, so the resulting effect still carries the original error type unless a user-defined type guard is used to narrow the type.

Signature

export declare const catchIf: {
  <E, EB extends E, A2, E2, R2>(
    refinement: Refinement<NoInfer<E>, EB>,
    f: (e: EB) => Effect<A2, E2, R2>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2 | Exclude<E, EB>, R2 | R>
  <E, A2, E2, R2>(
    predicate: Predicate<NoInfer<E>>,
    f: (e: NoInfer<E>) => Effect<A2, E2, R2>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E | E2, R2 | R>
  <A, E, R, EB extends E, A2, E2, R2>(
    self: Effect<A, E, R>,
    refinement: Refinement<E, EB>,
    f: (e: EB) => Effect<A2, E2, R2>
  ): Effect<A | A2, E2 | Exclude<E, EB>, R | R2>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    predicate: Predicate<E>,
    f: (e: E) => Effect<A2, E2, R2>
  ): Effect<A | A2, E | E2, R | R2>
}

Example

// Title: Catching Specific Errors with a Predicate
import { Effect, Random } from "effect"

class HttpError {
  readonly _tag = "HttpError"
}

class ValidationError {
  readonly _tag = "ValidationError"
}

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const program = Effect.gen(function* () {
  const n1 = yield* Random.next
  const n2 = yield* Random.next
  if (n1 < 0.5) {
    yield* Effect.fail(new HttpError())
  }
  if (n2 < 0.5) {
    yield* Effect.fail(new ValidationError())
  }
  return "some result"
})

//      ┌─── Effect<string, ValidationError, never>
//      ▼
const recovered = program.pipe(
  Effect.catchIf(
    // Only handle HttpError errors
    (error) => error._tag === "HttpError",
    () => Effect.succeed("Recovering from HttpError")
  )
)

Added in v2.0.0

catchSome

Catches and recovers from specific types of errors, allowing you to attempt recovery only for certain errors.

Details

catchSome lets you selectively catch and handle errors of certain types by providing a recovery effect for specific errors. If the error matches a condition, recovery is attempted; if not, it doesn’t affect the program. This function doesn’t alter the error type, meaning the error type remains the same as in the original effect.

Signature

export declare const catchSome: {
  <E, A2, E2, R2>(
    pf: (e: NoInfer<E>) => Option.Option<Effect<A2, E2, R2>>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E | E2, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    pf: (e: NoInfer<E>) => Option.Option<Effect<A2, E2, R2>>
  ): Effect<A | A2, E | E2, R | R2>
}

Example

// Title: Handling Specific Errors with Effect.catchSome
import { Effect, Random, Option } from "effect"

class HttpError {
  readonly _tag = "HttpError"
}

class ValidationError {
  readonly _tag = "ValidationError"
}

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const program = Effect.gen(function* () {
  const n1 = yield* Random.next
  const n2 = yield* Random.next
  if (n1 < 0.5) {
    yield* Effect.fail(new HttpError())
  }
  if (n2 < 0.5) {
    yield* Effect.fail(new ValidationError())
  }
  return "some result"
})

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const recovered = program.pipe(
  Effect.catchSome((error) => {
    // Only handle HttpError errors
    if (error._tag === "HttpError") {
      return Option.some(Effect.succeed("Recovering from HttpError"))
    } else {
      return Option.none()
    }
  })
)

Added in v2.0.0

catchSomeCause

Recovers from specific causes using a provided partial function.

Signature

export declare const catchSomeCause: {
  <E, A2, E2, R2>(
    f: (cause: Cause.Cause<NoInfer<E>>) => Option.Option<Effect<A2, E2, R2>>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E | E2, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    f: (cause: Cause.Cause<NoInfer<E>>) => Option.Option<Effect<A2, E2, R2>>
  ): Effect<A2 | A, E | E2, R2 | R>
}

Added in v2.0.0

catchSomeDefect

Recovers from specific defects using a provided partial function.

Details

catchSomeDefect allows you to handle specific defects, which are unexpected errors that can cause the program to stop. It uses a partial function to catch only certain defects and ignores others. The function does not handle expected errors (such as those caused by {@link fail}) or interruptions in execution (like those caused by {@link interrupt}).

This function provides a way to handle certain types of defects while allowing others to propagate and cause failure in the program.

Note: There is no sensible way to recover from defects. This method should be used only at the boundary between Effect and an external system, to transmit information on a defect for diagnostic or explanatory purposes.

How the Partial Function Works

The function provided to catchSomeDefect acts as a filter and a handler for defects:

  • It receives the defect as an input.
  • If the defect matches a specific condition (e.g., a certain error type), the function returns an Option.some containing the recovery logic.
  • If the defect does not match, the function returns Option.none, allowing the defect to propagate.

Signature

export declare const catchSomeDefect: {
  <A2, E2, R2>(
    pf: (defect: unknown) => Option.Option<Effect<A2, E2, R2>>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2 | E, R2 | R>
  <A, E, R, A2, E2, R2>(
    self: Effect<A, E, R>,
    pf: (defect: unknown) => Option.Option<Effect<A2, E2, R2>>
  ): Effect<A | A2, E | E2, R | R2>
}

Example

// Title: Handling Specific Defects
import { Effect, Cause, Option, Console } from "effect"

// Simulating a runtime error
const task = Effect.dieMessage("Boom!")

const program = Effect.catchSomeDefect(task, (defect) => {
  if (Cause.isIllegalArgumentException(defect)) {
    return Option.some(Console.log(`Caught an IllegalArgumentException defect: ${defect.message}`))
  }
  return Option.none()
})

// Since we are only catching IllegalArgumentException
// we will get an Exit.Failure because we simulated a runtime error.
// Effect.runPromiseExit(program).then(console.log)
// Output:
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Die',
//     defect: { _tag: 'RuntimeException' }
//   }
// }

Added in v2.0.0

catchTag

Catches and handles specific errors by their _tag field, which is used as a discriminator.

When to Use

catchTag is useful when your errors are tagged with a readonly _tag field that identifies the error type. You can use this function to handle specific error types by matching the _tag value. This allows for precise error handling, ensuring that only specific errors are caught and handled.

The error type must have a readonly _tag field to use catchTag. This field is used to identify and match errors.

Signature

export declare const catchTag: {
  <K extends E extends { _tag: string } ? E["_tag"] : never, E, A1, E1, R1>(
    k: K,
    f: (e: NoInfer<Extract<E, { _tag: K }>>) => Effect<A1, E1, R1>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A1 | A, E1 | Exclude<E, { _tag: K }>, R1 | R>
  <A, E, R, K extends E extends { _tag: string } ? E["_tag"] : never, R1, E1, A1>(
    self: Effect<A, E, R>,
    k: K,
    f: (e: Extract<E, { _tag: K }>) => Effect<A1, E1, R1>
  ): Effect<A | A1, E1 | Exclude<E, { _tag: K }>, R | R1>
}

Example

// Title: Handling Errors by Tag
import { Effect, Random } from "effect"

class HttpError {
  readonly _tag = "HttpError"
}

class ValidationError {
  readonly _tag = "ValidationError"
}

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const program = Effect.gen(function* () {
  const n1 = yield* Random.next
  const n2 = yield* Random.next
  if (n1 < 0.5) {
    yield* Effect.fail(new HttpError())
  }
  if (n2 < 0.5) {
    yield* Effect.fail(new ValidationError())
  }
  return "some result"
})

//      ┌─── Effect<string, ValidationError, never>
//      ▼
const recovered = program.pipe(
  // Only handle HttpError errors
  Effect.catchTag("HttpError", (_HttpError) => Effect.succeed("Recovering from HttpError"))
)

Added in v2.0.0

catchTags

Handles multiple errors in a single block of code using their _tag field.

When to Use

catchTags is a convenient way to handle multiple error types at once. Instead of using {@link catchTag} multiple times, you can pass an object where each key is an error type’s _tag, and the value is the handler for that specific error. This allows you to catch and recover from multiple error types in a single call.

The error type must have a readonly _tag field to use catchTag. This field is used to identify and match errors.

Signature

export declare const catchTags: {
  <
    E,
    Cases extends {
      [K in Extract<E, { _tag: string }>["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Effect<any, any, any>
    } & (unknown extends E ? {} : { [K in Exclude<keyof Cases, Extract<E, { _tag: string }>["_tag"]>]: never })
  >(
    cases: Cases
  ): <A, R>(
    self: Effect<A, E, R>
  ) => Effect<
    | A
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<infer A, any, any> ? A : never
      }[keyof Cases],
    | Exclude<E, { _tag: keyof Cases }>
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<any, infer E, any> ? E : never
      }[keyof Cases],
    | R
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<any, any, infer R> ? R : never
      }[keyof Cases]
  >
  <
    R,
    E,
    A,
    Cases extends {
      [K in Extract<E, { _tag: string }>["_tag"]]+?: (error: Extract<E, { _tag: K }>) => Effect<any, any, any>
    } & (unknown extends E ? {} : { [K in Exclude<keyof Cases, Extract<E, { _tag: string }>["_tag"]>]: never })
  >(
    self: Effect<A, E, R>,
    cases: Cases
  ): Effect<
    | A
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<infer A, any, any> ? A : never
      }[keyof Cases],
    | Exclude<E, { _tag: keyof Cases }>
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<any, infer E, any> ? E : never
      }[keyof Cases],
    | R
    | {
        [K in keyof Cases]: Cases[K] extends (...args: Array<any>) => Effect<any, any, infer R> ? R : never
      }[keyof Cases]
  >
}

Example

// Title: Handling Multiple Tagged Error Types at Once
import { Effect, Random } from "effect"

class HttpError {
  readonly _tag = "HttpError"
}

class ValidationError {
  readonly _tag = "ValidationError"
}

//      ┌─── Effect<string, HttpError | ValidationError, never>
//      ▼
const program = Effect.gen(function* () {
  const n1 = yield* Random.next
  const n2 = yield* Random.next
  if (n1 < 0.5) {
    yield* Effect.fail(new HttpError())
  }
  if (n2 < 0.5) {
    yield* Effect.fail(new ValidationError())
  }
  return "some result"
})

//      ┌─── Effect<string, never, never>
//      ▼
const recovered = program.pipe(
  Effect.catchTags({
    HttpError: (_HttpError) => Effect.succeed(`Recovering from HttpError`),
    ValidationError: (_ValidationError) => Effect.succeed(`Recovering from ValidationError`)
  })
)

Added in v2.0.0

cause

Retrieves the cause of a failure in an effect.

Details

This function allows you to expose the detailed cause of an effect, which includes a more precise representation of failures, such as error messages and defects.

When to Use

This function is helpful when you need to inspect the cause of a failure in an effect, giving you more information than just the error message. It can be used to log, handle, or analyze failures in more detail, including distinguishing between different types of defects (e.g., runtime exceptions, interruptions, etc.).

Signature

export declare const cause: <A, E, R>(self: Effect<A, E, R>) => Effect<Cause.Cause<E>, never, R>

Example

import { Effect, Console } from "effect"

//      ┌─── Effect<number, string, never>
//      ▼
const program = Effect.fail("Oh uh!").pipe(Effect.as(2))

//      ┌─── Effect<void, never, never>
//      ▼
const recovered = Effect.gen(function* () {
  const cause = yield* Effect.cause(program)
  yield* Console.log(cause)
})

Added in v2.0.0

eventually

Runs an effect repeatedly until it succeeds, ignoring errors.

Details

This function takes an effect and runs it repeatedly until the effect successfully completes. If the effect fails, it will ignore the error and retry the operation. This is useful when you need to perform a task that may fail occasionally, but you want to keep trying until it eventually succeeds. It works by repeatedly executing the effect until it no longer throws an error.

When to Use

Use this function when you want to retry an operation multiple times until it succeeds. It is helpful in cases where the operation may fail temporarily (e.g., a network request), and you want to keep trying without handling or worrying about the errors.

Signature

export declare const eventually: <A, E, R>(self: Effect<A, E, R>) => Effect<A, never, R>

Example

import { Effect } from "effect"

let counter = 0

const effect = Effect.try(() => {
  counter++
  if (counter < 3) {
    console.log("running effect")
    throw new Error("error")
  } else {
    console.log("effect done")
    return "some result"
  }
})

const program = Effect.eventually(effect)

// Effect.runPromise(program).then(console.log)
// Output:
// running effect
// running effect
// effect done
// some result

Added in v2.0.0

ignore

Discards both the success and failure values of an effect.

When to Use

ignore allows you to run an effect without caring about its result, whether it succeeds or fails. This is useful when you only care about the side effects of the effect and do not need to handle or process its outcome.

Signature

export declare const ignore: <A, E, R>(self: Effect<A, E, R>) => Effect<void, never, R>

Example

// Title: Using Effect.ignore to Discard Values
import { Effect } from "effect"

//      ┌─── Effect<number, string, never>
//      ▼
const task = Effect.fail("Uh oh!").pipe(Effect.as(5))

//      ┌─── Effect<void, never, never>
//      ▼
const program = Effect.ignore(task)

Added in v2.0.0

ignoreLogged

Ignores the result of an effect but logs any failures.

Details

This function takes an effect and returns a new effect that ignores whether the original effect succeeds or fails. However, if the effect fails, it will log the failure at the Debug level, so you can keep track of any issues that arise.

When to Use

This is useful in scenarios where you want to continue with your program regardless of the result of the effect, but you still want to be aware of potential failures that may need attention later.

Signature

export declare const ignoreLogged: <A, E, R>(self: Effect<A, E, R>) => Effect<void, never, R>

Added in v2.0.0

parallelErrors

Combines all errors from concurrent operations into a single error.

Details

This function is used when you have multiple operations running at the same time, and you want to capture all the errors that occur across those operations. Instead of handling each error separately, it combines all the errors into one unified error.

When to Use

When using this function, any errors that occur in the concurrently running operations will be grouped together into a single error. This helps simplify error handling in cases where you don’t need to differentiate between each failure, but simply want to know that multiple failures occurred.

Signature

export declare const parallelErrors: <A, E, R>(self: Effect<A, E, R>) => Effect<A, Array<E>, R>

Example

import { Effect } from "effect"

const fail1 = Effect.fail("Oh uh!")
const fail2 = Effect.fail("Oh no!")
const die = Effect.dieMessage("Boom!")

// Run all effects concurrently and capture all errors
const program = Effect.all([fail1, fail2, die], {
  concurrency: "unbounded"
}).pipe(Effect.asVoid, Effect.parallelErrors)

// Effect.runPromiseExit(program).then(console.log)
// Output:
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: { _id: 'Cause', _tag: 'Fail', failure: [ 'Oh uh!', 'Oh no!' ] }
// }

Added in v2.0.0

retry

Retries a failing effect based on a defined retry policy.

Details

The Effect.retry function takes an effect and a {@link Schedule} policy, and will automatically retry the effect if it fails, following the rules of the policy.

If the effect ultimately succeeds, the result will be returned.

If the maximum retries are exhausted and the effect still fails, the failure is propagated.

When to Use

This can be useful when dealing with intermittent failures, such as network issues or temporary resource unavailability. By defining a retry policy, you can control the number of retries, the delay between them, and when to stop retrying.

Signature

export declare const retry: {
  <E, O extends Retry.Options<E>>(options: O): <A, R>(self: Effect<A, E, R>) => Retry.Return<R, E, A, O>
  <B, E, R1>(policy: Schedule.Schedule<B, NoInfer<E>, R1>): <A, R>(self: Effect<A, E, R>) => Effect<A, E, R1 | R>
  <A, E, R, O extends Retry.Options<E>>(self: Effect<A, E, R>, options: O): Retry.Return<R, E, A, O>
  <A, E, R, B, R1>(self: Effect<A, E, R>, policy: Schedule.Schedule<B, E, R1>): Effect<A, E, R1 | R>
}

Example

// Title: Retrying with a Fixed Delay
import { Effect, Schedule } from "effect"

let count = 0

// Simulates an effect with possible failures
const task = Effect.async<string, Error>((resume) => {
  if (count <= 2) {
    count++
    console.log("failure")
    resume(Effect.fail(new Error()))
  } else {
    console.log("success")
    resume(Effect.succeed("yay!"))
  }
})

// Define a repetition policy using a fixed delay between retries
const policy = Schedule.fixed("100 millis")

const repeated = Effect.retry(task, policy)

// Effect.runPromise(repeated).then(console.log)
// Output:
// failure
// failure
// failure
// success
// yay!

Example

// Title: Retrying a Task up to 5 times
import { Effect } from "effect"

let count = 0

// Simulates an effect with possible failures
const task = Effect.async<string, Error>((resume) => {
  if (count <= 2) {
    count++
    console.log("failure")
    resume(Effect.fail(new Error()))
  } else {
    console.log("success")
    resume(Effect.succeed("yay!"))
  }
})

// Retry the task up to 5 times
// Effect.runPromise(Effect.retry(task, { times: 5 }))
// Output:
// failure
// failure
// failure
// success

Example

// Title: Retrying Until a Specific Condition is Met
import { Effect } from "effect"

let count = 0

// Define an effect that simulates varying error on each invocation
const action = Effect.failSync(() => {
  console.log(`Action called ${++count} time(s)`)
  return `Error ${count}`
})

// Retry the action until a specific condition is met
const program = Effect.retry(action, {
  until: (err) => err === "Error 3"
})

// Effect.runPromiseExit(program).then(console.log)
// Output:
// Action called 1 time(s)
// Action called 2 time(s)
// Action called 3 time(s)
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: { _id: 'Cause', _tag: 'Fail', failure: 'Error 3' }
// }

Added in v2.0.0

retryOrElse

Retries a failing effect and runs a fallback effect if retries are exhausted.

Details

The Effect.retryOrElse function attempts to retry a failing effect multiple times according to a defined {@link Schedule} policy.

If the retries are exhausted and the effect still fails, it runs a fallback effect instead.

When to Use

This function is useful when you want to handle failures gracefully by specifying an alternative action after repeated failures.

Signature

export declare const retryOrElse: {
  <A1, E, R1, A2, E2, R2>(
    policy: Schedule.Schedule<A1, NoInfer<E>, R1>,
    orElse: (e: NoInfer<E>, out: A1) => Effect<A2, E2, R2>
  ): <A, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2, R1 | R2 | R>
  <A, E, R, A1, R1, A2, E2, R2>(
    self: Effect<A, E, R>,
    policy: Schedule.Schedule<A1, NoInfer<E>, R1>,
    orElse: (e: NoInfer<E>, out: A1) => Effect<A2, E2, R2>
  ): Effect<A | A2, E2, R | R1 | R2>
}

Example

// Title: Retrying with Fallback
import { Effect, Schedule, Console } from "effect"

let count = 0

// Simulates an effect with possible failures
const task = Effect.async<string, Error>((resume) => {
  if (count <= 2) {
    count++
    console.log("failure")
    resume(Effect.fail(new Error()))
  } else {
    console.log("success")
    resume(Effect.succeed("yay!"))
  }
})

// Retry the task with a delay between retries and a maximum of 2 retries
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")

// If all retries fail, run the fallback effect
const repeated = Effect.retryOrElse(
  task,
  policy,
  // fallback
  () => Console.log("orElse").pipe(Effect.as("default value"))
)

// Effect.runPromise(repeated).then(console.log)
// Output:
// failure
// failure
// failure
// orElse
// default value

Added in v2.0.0

sandbox

Transforms an effect to expose detailed error causes.

Details

This function enhances an effect by providing detailed information about any error, defect, or interruption that may occur during its execution. It modifies the error channel of the effect so that it includes a full cause of the failure, wrapped in a Cause<E> type.

After applying this function, you can use operators like {@link catchAll} and {@link catchTags} to handle specific types of errors.

If you no longer need the detailed cause information, you can revert the changes using {@link unsandbox} to return to the original error-handling behavior.

Signature

export declare const sandbox: <A, E, R>(self: Effect<A, E, R>) => Effect<A, Cause.Cause<E>, R>

Example

import { Effect, Console } from "effect"

//      ┌─── Effect<string, Error, never>
//      ▼
const task = Effect.fail(new Error("Oh uh!")).pipe(Effect.as("primary result"))

//      ┌─── Effect<string, Cause<Error>, never>
//      ▼
const sandboxed = Effect.sandbox(task)

const program = Effect.catchTags(sandboxed, {
  Die: (cause) => Console.log(`Caught a defect: ${cause.defect}`).pipe(Effect.as("fallback result on defect")),
  Interrupt: (cause) =>
    Console.log(`Caught a defect: ${cause.fiberId}`).pipe(Effect.as("fallback result on fiber interruption")),
  Fail: (cause) => Console.log(`Caught a defect: ${cause.error}`).pipe(Effect.as("fallback result on failure"))
})

// Restore the original error handling with unsandbox
const main = Effect.unsandbox(program)

// Effect.runPromise(main).then(console.log)
// Output:
// Caught a defect: Oh uh!
// fallback result on failure

Added in v2.0.0

tryMap

Returns an effect that maps its success using the specified side-effecting try function, converting any errors into typed failed effects using the catch function.

Signature

export declare const tryMap: {
  <A, B, E1>(options: {
    readonly try: (a: A) => B
    readonly catch: (error: unknown) => E1
  }): <E, R>(self: Effect<A, E, R>) => Effect<B, E1 | E, R>
  <A, E, R, B, E1>(
    self: Effect<A, E, R>,
    options: { readonly try: (a: A) => B; readonly catch: (error: unknown) => E1 }
  ): Effect<B, E | E1, R>
}

Added in v2.0.0

tryMapPromise

Returns an effect that maps its success using the specified side-effecting try function, converting any promise rejections into typed failed effects using the catch function.

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

Signature

export declare const tryMapPromise: {
  <A, B, E1>(options: {
    readonly try: (a: A, signal: AbortSignal) => PromiseLike<B>
    readonly catch: (error: unknown) => E1
  }): <E, R>(self: Effect<A, E, R>) => Effect<B, E1 | E, R>
  <A, E, R, B, E1>(
    self: Effect<A, E, R>,
    options: { readonly try: (a: A, signal: AbortSignal) => PromiseLike<B>; readonly catch: (error: unknown) => E1 }
  ): Effect<B, E | E1, R>
}

Added in v2.0.0

unsandbox

The unsandbox function is used to revert an effect that has been sandboxed by {@link sandbox}. When you apply unsandbox, the effect’s error channel is restored to its original state, without the detailed Cause<E> information. This means that any underlying causes of errors, defects, or fiber interruptions are no longer exposed in the error channel.

This function is useful when you want to remove the detailed error tracking provided by sandbox and return to the standard error handling for your effect. Once unsandboxed, the effect behaves as if sandbox was never applied.

Signature

export declare const unsandbox: <A, E, R>(self: Effect<A, Cause.Cause<E>, R>) => Effect<A, E, R>

Added in v2.0.0

Fallback

firstSuccessOf

Runs a sequence of effects and returns the result of the first successful one.

Details

This function allows you to execute a collection of effects in sequence, stopping at the first success. If an effect succeeds, its result is immediately returned, and no further effects in the sequence are executed. However, if all the effects fail, the function will return the error of the last effect.

The execution is sequential, meaning that effects are evaluated one at a time in the order they are provided. This ensures predictable behavior and avoids unnecessary computations.

If the collection of effects is empty, an IllegalArgumentException is thrown, indicating that the operation is invalid without any effects to try.

When to Use

This is particularly useful when you have multiple fallback strategies or alternative sources to obtain a result, such as attempting multiple APIs, retrieving configurations, or accessing resources in a prioritized manner.

Signature

export declare const firstSuccessOf: <Eff extends Effect<any, any, any>>(
  effects: Iterable<Eff>
) => Effect<Effect.Success<Eff>, Effect.Error<Eff>, Effect.Context<Eff>>

Example

import { Effect, Console } from "effect"

interface Config {
  host: string
  port: number
  apiKey: string
}

// Create a configuration object with sample values
const makeConfig = (name: string): Config => ({
  host: `${name}.example.com`,
  port: 8080,
  apiKey: "12345-abcde"
})

// Simulate retrieving configuration from a remote node
const remoteConfig = (name: string): Effect.Effect<Config, Error> =>
  Effect.gen(function* () {
    // Simulate node3 being the only one with available config
    if (name === "node3") {
      yield* Console.log(`Config for ${name} found`)
      return makeConfig(name)
    } else {
      yield* Console.log(`Unavailable config for ${name}`)
      return yield* Effect.fail(new Error(`Config not found for ${name}`))
    }
  })

// Define the master configuration and potential fallback nodes
const masterConfig = remoteConfig("master")
const nodeConfigs = ["node1", "node2", "node3", "node4"].map(remoteConfig)

// Attempt to find a working configuration,
// starting with the master and then falling back to other nodes
const config = Effect.firstSuccessOf([masterConfig, ...nodeConfigs])

// Run the effect to retrieve the configuration
const result = Effect.runSync(config)

console.log(result)
// Output:
// Unavailable config for master
// Unavailable config for node1
// Unavailable config for node2
// Config for node3 found
// { host: 'node3.example.com', port: 8080, apiKey: '12345-abcde' }

Added in v2.0.0

orElse

Attempts one effect, and if it fails, falls back to another effect.

Details

This function allows you to try executing an effect, and if it fails (produces an error), a fallback effect is executed instead. The fallback effect is defined as a lazy argument, meaning it will only be evaluated if the first effect fails. This provides a way to recover from errors by specifying an alternative path of execution.

The error type of the resulting effect will be that of the fallback effect, as the first effect’s error is replaced when the fallback is executed.

Signature

export declare const orElse: {
  <A2, E2, R2>(that: LazyArg<Effect<A2, E2, R2>>): <A, E, R>(self: Effect<A, E, R>) => Effect<A2 | A, E2, R2 | R>
  <A, E, R, A2, E2, R2>(self: Effect<A, E, R>, that: LazyArg<Effect<A2, E2, R2>>): Effect<A2 | A, E2, R2 | R>
}

Example

import { Effect } from "effect"

const success = Effect.succeed("success")
const failure = Effect.fail("failure")
const fallback = Effect.succeed("fallback")

// Try the success effect first, fallback is not used
const program1 = Effect.orElse(success, () => fallback)
console.log(Effect.runSync(program1))
// Output: "success"

// Try the failure effect first, fallback is used
const program2 = Effect.orElse(failure, () => fallback)
console.log(Effect.runSync(program2))
// Output: "fallback"

Added in v2.0.0

orElseFail

Replaces the failure of an effect with a custom failure value.

Details

This function allows you to handle the failure of an effect by replacing it with a predefined failure value. If the effect fails, the new failure value provided by the evaluate function will be returned instead of the original failure. If the effect succeeds, the original success value is returned unchanged.

When to Use

This is particularly useful when you want to standardize error handling or provide a consistent failure value for specific operations. It simplifies error management by ensuring that all failures are replaced with a controlled alternative.

Signature

export declare const orElseFail: {
  <E2>(evaluate: LazyArg<E2>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E2, R>
  <A, E, R, E2>(self: Effect<A, E, R>, evaluate: LazyArg<E2>): Effect<A, E2, R>
}

Example

import { Effect } from "effect"

const validate = (age: number): Effect.Effect<number, string> => {
  if (age < 0) {
    return Effect.fail("NegativeAgeError")
  } else if (age < 18) {
    return Effect.fail("IllegalAgeError")
  } else {
    return Effect.succeed(age)
  }
}

const program = Effect.orElseFail(validate(-1), () => "invalid age")

console.log(Effect.runSyncExit(program))
// Output:
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: { _id: 'Cause', _tag: 'Fail', failure: 'invalid age' }
// }

Added in v2.0.0

orElseSucceed

Ensures the effect always succeeds by replacing failures with a default success value.

Details

This function transforms an effect that may fail into one that cannot fail by replacing any failure with a provided success value. If the original effect fails, the failure is “swallowed,” and the specified success value is returned instead. If the original effect succeeds, its value remains unchanged.

When to Use

This is especially useful for providing default values in case of failure, ensuring that an effect always completes successfully. By using this function, you can avoid the need for complex error handling and guarantee a fallback result.

Signature

export declare const orElseSucceed: {
  <A2>(evaluate: LazyArg<A2>): <A, E, R>(self: Effect<A, E, R>) => Effect<A2 | A, never, R>
  <A, E, R, A2>(self: Effect<A, E, R>, evaluate: LazyArg<A2>): Effect<A | A2, never, R>
}

Example

import { Effect } from "effect"

const validate = (age: number): Effect.Effect<number, string> => {
  if (age < 0) {
    return Effect.fail("NegativeAgeError")
  } else if (age < 18) {
    return Effect.fail("IllegalAgeError")
  } else {
    return Effect.succeed(age)
  }
}

const program = Effect.orElseSucceed(validate(-1), () => 18)

console.log(Effect.runSyncExit(program))
// Output:
// { _id: 'Exit', _tag: 'Success', value: 18 }

Added in v2.0.0

Fiber Refs

getFiberRefs

Returns a collection of all FiberRef values for the fiber running this effect.

Signature

export declare const getFiberRefs: Effect<FiberRefs.FiberRefs, never, never>

Added in v2.0.0

inheritFiberRefs

Inherits values from all FiberRef instances into current fiber.

Signature

export declare const inheritFiberRefs: (childFiberRefs: FiberRefs.FiberRefs) => Effect<void>

Added in v2.0.0

locally

Signature

export declare const locally: {
  <A>(self: FiberRef.FiberRef<A>, value: A): <B, E, R>(use: Effect<B, E, R>) => Effect<B, E, R>
  <B, E, R, A>(use: Effect<B, E, R>, self: FiberRef.FiberRef<A>, value: A): Effect<B, E, R>
}

Added in v2.0.0

locallyScoped

Signature

export declare const locallyScoped: {
  <A>(value: A): (self: FiberRef.FiberRef<A>) => Effect<void, never, Scope.Scope>
  <A>(self: FiberRef.FiberRef<A>, value: A): Effect<void, never, Scope.Scope>
}

Added in v2.0.0

locallyScopedWith

Signature

export declare const locallyScopedWith: {
  <A>(f: (a: A) => A): (self: FiberRef.FiberRef<A>) => Effect<void, never, Scope.Scope>
  <A>(self: FiberRef.FiberRef<A>, f: (a: A) => A): Effect<void, never, Scope.Scope>
}

Added in v2.0.0

locallyWith

Signature

export declare const locallyWith: {
  <A>(self: FiberRef.FiberRef<A>, f: (a: A) => A): <B, E, R>(use: Effect<B, E, R>) => Effect<B, E, R>
  <B, E, R, A>(use: Effect<B, E, R>, self: FiberRef.FiberRef<A>, f: (a: A) => A): Effect<B, E, R>
}

Added in v2.0.0

patchFiberRefs

Applies the specified changes to the FiberRef values for the fiber running this workflow.

Signature

export declare const patchFiberRefs: (patch: FiberRefsPatch.FiberRefsPatch) => Effect<void>

Added in v2.0.0

setFiberRefs

Sets the FiberRef values for the fiber running this effect to the values in the specified collection of FiberRef values.

Signature

export declare const setFiberRefs: (fiberRefs: FiberRefs.FiberRefs) => Effect<void>

Added in v2.0.0

updateFiberRefs

Updates the FiberRef values for the fiber running this effect using the specified function.

Signature

export declare const updateFiberRefs: (
  f: (fiberId: FiberId.Runtime, fiberRefs: FiberRefs.FiberRefs) => FiberRefs.FiberRefs
) => Effect<void>

Added in v2.0.0

Filtering

filter

Filters an iterable using the specified effectful predicate.

Details

This function filters a collection (an iterable) by applying an effectful predicate.

The predicate is a function that takes an element and its index, and it returns an effect that evaluates to a boolean.

The function processes each element in the collection and keeps only those that satisfy the condition defined by the predicate.

Options

You can also adjust the behavior with options such as concurrency, batching, or whether to negate the condition.

When to Use

This function allows you to selectively keep or remove elements based on a condition that may involve asynchronous or side-effect-causing operations.

Signature

export declare const filter: {
  <A, E, R>(
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly negate?: boolean | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): (elements: Iterable<A>) => Effect<Array<A>, E, R>
  <A, E, R>(
    elements: Iterable<A>,
    predicate: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>,
    options?:
      | {
          readonly concurrency?: Concurrency | undefined
          readonly batching?: boolean | "inherit" | undefined
          readonly negate?: boolean | undefined
          readonly concurrentFinalizers?: boolean | undefined
        }
      | undefined
  ): Effect<Array<A>, E, R>
}

Example

import { Effect } from "effect"

const numbers = [1, 2, 3, 4, 5]
const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)

const program = Effect.gen(function* () {
  const result = yield* Effect.filter(numbers, predicate)
  console.log(result)
})

// Effect.runFork(program)
// Output: [2, 4]

Added in v2.0.0

filterEffectOrElse

Filters an effect with an effectful predicate, falling back to an alternative effect if the predicate fails.

Details

This function applies a predicate to the result of an effect. If the predicate evaluates to false, the effect falls back to the orElse effect. The orElse effect can produce an alternative value or perform additional computations.

Signature

export declare const filterEffectOrElse: {
  <A, E2, R2, A2, E3, R3>(options: {
    readonly predicate: (a: NoInfer<A>) => Effect<boolean, E2, R2>
    readonly orElse: (a: NoInfer<A>) => Effect<A2, E3, R3>
  }): <E, R>(self: Effect<A, E, R>) => Effect<A | A2, E | E2 | E3, R | R2 | R3>
  <A, E, R, E2, R2, A2, E3, R3>(
    self: Effect<A, E, R>,
    options: { readonly predicate: (a: A) => Effect<boolean, E2, R2>; readonly orElse: (a: A) => Effect<A2, E3, R3> }
  ): Effect<A | A2, E | E2 | E3, R | R2 | R3>
}

Example

import { Effect, pipe } from "effect"

// Define a user interface
interface User {
  readonly name: string
}

// Simulate an asynchronous authentication function
declare const auth: () => Promise<User | null>

const program = pipe(
  Effect.promise(() => auth()),
  // Use filterEffectOrElse with an effectful predicate
  Effect.filterEffectOrElse({
    predicate: (user) => Effect.succeed(user !== null),
    orElse: (user) => Effect.fail(new Error(`Unauthorized user: ${user}`))
  })
)

Added in v3.13.0

filterEffectOrFail

Filters an effect with an effectful predicate, failing with a custom error if the predicate fails.

Details

This function applies a predicate to the result of an effect. If the predicate evaluates to false, the effect fails with a custom error generated by the orFailWith function.

When to Use

This is useful for enforcing constraints and treating violations as recoverable errors.

Signature

export declare const filterEffectOrFail: {
  <A, E2, R2, E3>(options: {
    readonly predicate: (a: NoInfer<A>) => Effect<boolean, E2, R2>
    readonly orFailWith: (a: NoInfer<A>) => E3
  }): <E, R>(self: Effect<A, E, R>) => Effect<A, E | E2 | E3, R | R2>
  <A, E, R, E2, R2, E3>(
    self: Effect<A, E, R>,
    options: { readonly predicate: (a: A) => Effect<boolean, E2, R2>; readonly orFailWith: (a: A) => E3 }
  ): Effect<A, E | E2 | E3, R | R2>
}

Example

import { Effect, pipe } from "effect"

// Define a user interface
interface User {
  readonly name: string
}

// Simulate an asynchronous authentication function
declare const auth: () => Promise<User | null>

const program = pipe(
  Effect.promise(() => auth()),
  // Use filterEffectOrFail with an effectful predicate
  Effect.filterEffectOrFail({
    predicate: (user) => Effect.succeed(user !== null),
    orFailWith: () => new Error("Unauthorized")
  })
)

Added in v3.13.0

filterMap

Filters and maps elements sequentially in one operation.

This function processes each element one by one. It applies a function that returns an Option to each element. If the function returns Some, the element is kept; if it returns None, the element is removed. The operation is done sequentially for each element.

Signature

export declare const filterMap: {
  <Eff extends Effect<any, any, any>, B>(
    pf: (a: Effect.Success<Eff>) => Option.Option<B>
  ): (elements: Iterable<Eff>) => Effect<Array<B>, Effect.Error<Eff>, Effect.Context<Eff>>
  <Eff extends Effect<any, any, any>, B>(
    elements: Iterable<Eff>,
    pf: (a: Effect.Success<Eff>) => Option.Option<B>
  ): Effect<Array<B>, Effect.Error<Eff>, Effect.Context<Eff>>
}

Example

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

const task = (n: number) =>
  Effect.succeed(n).pipe(Effect.delay(1000 - n * 100), Effect.tap(Console.log(`task${n} done`)))

const program = Effect.filterMap([task(1), task(2), task(3), task(4)], (n) =>
  n % 2 === 0 ? Option.some(n) : Option.none()
)

// Effect.runPromise(program).then(console.log)
// Output:
// task1 done
// task2 done
// task3 done
// task4 done
// [ 2, 4 ]

Added in v2.0.0

filterOrDie

Filters an effect, dying with a custom defect if the predicate fails.

Details

This function applies a predicate to the result of an effect. If the predicate evaluates to false, the effect dies with a custom defect generated by the orDieWith function.

When to Use

This is useful for enforcing constraints on values and treating violations as fatal program errors.

Signature

export declare const filterOrDie: {
  <A, B extends A>(
    refinement: Refinement<NoInfer<A>, B>,
    orDieWith: (a: NoInfer<A>) => unknown
  ): <E, R>(self: Effect<A, E, R>) => Effect<B, E, R>
  <A>(
    predicate: Predicate<NoInfer<A>>,
    orDieWith: (a: NoInfer<A>) => unknown
  ): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R, B extends A>(
    self: Effect<A, E, R>,
    refinement: Refinement<A, B>,
    orDieWith: (a: A) => unknown
  ): Effect<B, E, R>
  <A, E, R>(self: Effect<A, E, R>, predicate: Predicate<A>, orDieWith: (a: A) => unknown): Effect<A, E, R>
}

Added in v2.0.0

filterOrDieMessage

Filters an effect, dying with a custom message if the predicate fails.

Details

This function works like {@link filterOrDie} but allows you to specify a custom error message to describe the reason for the failure. The message is included in the defect when the predicate evaluates to false.

Signature

export declare const filterOrDieMessage: {
  <A, B extends A>(
    refinement: Refinement<NoInfer<A>, B>,
    message: string
  ): <E, R>(self: Effect<A, E, R>) => Effect<B, E, R>
  <A>(predicate: Predicate<NoInfer<A>>, message: string): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
  <A, E, R, B extends A>(self: Effect<A, E, R>, refinement: Refinement<A, B>, message: string): Effect<B, E, R>
  <A, E, R>(self: Effect<A, E, R>, predicate: Predicate<A>, message: string): Effect<A, E, R>
}

Added in v2.0.0

filterOrElse

Filters an effect, providing an alternative effect if the predicate fails.

Details

This function applies a predicate to the result of an effect. If the predicate evaluates to false, it executes the orElse effect instead. The orElse effect can produce an alternative value or perform additional computations.

Signature

export declare const filterOrElse: {
  <A, B extends A, C, E2, R2>(
    refinement: Refinement<NoInfer<A>, B>,
    orElse: (a: NoInfer<A>) => Effect<C, E2, R2>
  ): <E, R>(self: Effect<A, E, R>) => Effect<B | C, E2 | E, R2 | R>
  <A, B, E2, R2>(
    predicate: Predicate<NoInfer<A>>,
    orElse: (a: NoInfer<A>) => Effect<B, E2, R2>
  ): <E, R>(self: Effect<A, E, R>) => Effect<A | B, E2 | E, R2 | R>
  <A, E, R, B extends A, C, E2, R2>(
    self: Effect<A, E, R>,
    refinement: Refinement<A, B>,
    orElse: (a: A) => Effect<C, E2, R2>
  ): Effect<B | C, E | E2, R | R2>
  <A, E, R, B, E2, R2>(
    self: Effect<A, E, R>,
    predicate: Predicate<A>,
    orElse: (a: A) => Effect<B, E2, R2>
  ): Effect<A | B, E | E2, R | R2>
}

Added in v2.0.0

filterOrFail

Filters an effect, failing with a custom error if the predicate fails.

Details

This function applies a predicate to the result of an effect. If the predicate evaluates to false, the effect fails with a custom error generated by the orFailWith function.

When to Use

This is useful for enforcing constraints and treating violations as recoverable errors.

Providing a Guard

In addition to the filtering capabilities discussed earlier, you have the option to further refine and narrow down the type of the success channel by providing a user-defined type guard. Let’s explore this concept through an example:

Signature

export declare const filterOrFail: {
  <A, B extends A, E2>(
    refinement: Refinement<NoInfer<A>, B>,
    orFailWith: (a: NoInfer<A>) => E2
  ): <E, R>(self: Effect<A, E, R>) => Effect<B, E2 | E, R>
  <A, E2>(
    predicate: Predicate<NoInfer<A>>,
    orFailWith: (a: NoInfer<A>) => E2
  ): <E, R>(self: Effect<A, E, R>) => Effect<A, E2 | E, R>
  <A, B extends A>(
    refinement: Refinement<NoInfer<A>, B>
  ): <E, R>(self: Effect<A, E, R>) => Effect<B, Cause.NoSuchElementException | E, R>
  <A>(predicate: Predicate<NoInfer<A>>): <E, R>(self: Effect<A, E, R>) => Effect<A, Cause.NoSuchElementException | E, R>
  <A, E, R, B extends A, E2>(
    self: Effect<A, E, R>,
    refinement: Refinement<A, B>,
    orFailWith: (a: A) => E2
  ): Effect<B, E | E2, R>
  <A, E, R, E2>(self: Effect<A, E, R>, predicate: Predicate<A>, orFailWith: (a: A) => E2): Effect<A, E | E2, R>
  <A, E, R, B extends A>(
    self: Effect<A, E, R>,
    refinement: Refinement<A, B>
  ): Effect<B, E | Cause.NoSuchElementException, R>
  <A, E, R>(self: Effect<A, E, R>, predicate: Predicate<A>): Effect<A, E | Cause.NoSuchElementException, R>
}

Example

import { Effect, pipe } from "effect"

// Define a user interface
interface User {
  readonly name: string
}

// Simulate an asynchronous authentication function
declare const auth: () => Promise<User | null>

const program = pipe(
  Effect.promise(() => auth()),
  // Use filterOrFail with a custom type guard to ensure user is not null
  Effect.filterOrFail(
    (user): user is User => user !== null, // Type guard
    () => new Error("Unauthorized")
  ),
  // 'user' now has the type `User` (not `User | null`)
  Effect.andThen((user) => user.name)
)

Added in v2.0.0

Guards

isEffect

Checks if a given value is an Effect value.

When to Use

This function can be useful for checking the type of a value before attempting to operate on it as an Effect value. For example, you could use Effect.isEffect to check the type of a value before using it as an argument to a function that expects an Effect value.

Signature

export declare const isEffect: (u: unknown) => u is Effect<unknown, unknown, unknown>

Added in v2.0.0

Interruption

allowInterrupt

Allows interruption of the current fiber, even in uninterruptible regions.

Details

This effect checks whether any other fibers are attempting to interrupt the current fiber. If so, it allows the current fiber to perform a self-interruption.

When to Use

This is useful in situations where you want to allow interruption to happen even in regions of the code that are normally uninterruptible.

Signature

export declare const allowInterrupt: Effect<void, never, never>

Added in v2.0.0

checkInterruptible

Checks if interruption is allowed and executes a callback accordingly.

Details

This function checks the current interrupt status of the running fiber. It then calls the provided callback, passing a boolean indicating whether interruption is allowed.

When to Use

This is useful for handling specific logic based on whether the current operation can be interrupted, such as when performing asynchronous operations or handling cancellation.

Signature

export declare const checkInterruptible: <A, E, R>(f: (isInterruptible: boolean) => Effect<A, E, R>) => Effect<A, E, R>

Example

import { Console, Effect } from "effect"

const program = Effect.gen(function* () {
  yield* Effect.checkInterruptible((isInterruptible) => {
    if (isInterruptible) {
      return Console.log("You can interrupt this operation.")
    } else {
      return Console.log("This operation cannot be interrupted.")
    }
  })
})

// Effect.runPromise(program)
// Output: You can interrupt this operation.

// Effect.runPromise(program.pipe(Effect.uninterruptible))
// Output: This operation cannot be interrupted.

Added in v2.0.0

disconnect

Provides a way to handle timeouts in uninterruptible effects, allowing them to continue in the background while the main control flow proceeds with the timeout error.

Details

The disconnect function allows an uninterruptible effect to continue running in the background, while enabling the main control flow to immediately recognize a timeout condition. This is useful when you want to avoid blocking the program due to long-running tasks, especially when those tasks do not need to affect the flow of the rest of the program.

Without disconnect, an uninterruptible effect will ignore the timeout and continue executing until it completes. The timeout error will only be assessed after the effect finishes, which can cause delays in recognizing a timeout.

With disconnect, the uninterruptible effect proceeds in the background while the main program flow can immediately handle the timeout error or trigger alternative logic. This enables faster timeout handling without waiting for the completion of the long-running task.

Signature

export declare const disconnect: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>

Example

import { Effect } from "effect"

const longRunningTask = Effect.gen(function* () {
  console.log("Start heavy processing...")
  yield* Effect.sleep("5 seconds") // Simulate a long process
  console.log("Heavy processing done.")
  return "Data processed"
})

const timedEffect = longRunningTask.pipe(
  Effect.uninterruptible,
  // Allows the task to finish in the background if it times out
  Effect.disconnect,
  Effect.timeout("1 second")
)

// Effect.runPromiseExit(timedEffect).then(console.log)
// Output:
// Start heavy processing...
// {
//   _id: 'Exit',
//   _tag: 'Failure',
//   cause: {
//     _id: 'Cause',
//     _tag: 'Fail',
//     failure: { _tag: 'TimeoutException' }
//   }
// }
// Heavy processing done.

Added in v2.0.0

interrupt

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 {@link runPromiseExit}.

Signature

export declare const interrupt: Effect<never, never, never>

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: ...
//     }
//   }
// }

Added in v2.0.0

interruptWith

Signature

export declare const interruptWith: (fiberId: FiberId.FiberId) => Effect<never>

Added in v2.0.0

interruptible

Marks an effect as interruptible.

Signature

export declare const interruptible: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>

Added in v2.0.0

interruptibleMask

This function behaves like {@link interruptible}, but it also provides a restore function. This function can be used to restore the interruptibility of any specific region of code.

Signature

export declare const interruptibleMask: <A, E, R>(
  f: (restore: <AX, EX, RX>(effect: Effect<AX, EX, RX>) => Effect<AX, EX, RX>) => Effect<A, E, R>
) => Effect<A, E, R>

Added in v2.0.0

onInterrupt

Registers a cleanup effect to run when an effect is interrupted.

Details

This function allows you to specify an effect to run when the fiber is interrupted. This effect will be executed when the fiber is interrupted, allowing you to perform cleanup or other actions.

Signature

export declare const onInterrupt: {
  <X, R2>(
    cleanup: (interruptors: HashSet.HashSet<FiberId.FiberId>) => Effect<X, never, R2>
  ): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R2 | R>
  <A, E, R, X, R2>(
    self: Effect<A, E, R>,
    cleanup: (interruptors: HashSet.HashSet<FiberId.FiberId>) => Effect<X, never, R2>
  ): Effect<A, E, R | R2>
}

Example

// Title: Running a Cleanup Action on Interruption
import { Console, Effect } from "effect"

// This handler is executed when the fiber is interrupted
const handler = Effect.onInterrupt((_fibers) => Console.log("Cleanup completed"))

const success = Console.log("Task completed").pipe(Effect.as("some result"), handler)

// Effect.runFork(success)
// Output:
// Task completed

const failure = Console.log("Task failed").pipe(Effect.andThen(Effect.fail("some error")), handler)

// Effect.runFork(failure)
// Output:
// Task failed

const interruption = Console.log("Task interrupted").pipe(Effect.andThen(Effect.interrupt), handler)

// Effect.runFork(interruption)
// Output:
// Task interrupted
// Cleanup completed

Added in v2.0.0

uninterruptible

Marks an effect as uninterruptible.

Signature

export declare const uninterruptible: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>

Added in v2.0.0

uninterruptibleMask

This function behaves like {@link uninterruptible}, but it also provides a restore function. This function can be used to restore the interruptibility of any specific region of code.

Signature

export declare const uninterruptibleMask: <A, E, R>(
  f: (restore: <AX, EX, RX>(effect: Effect<AX, EX, RX>) => Effect<AX, EX, RX>) => Effect<A, E, R>
) => Effect<A, E, R>

Added in v2.0.0

Latch

Latch (interface)

A Latch is a synchronization primitive that allows you to control the execution of fibers based on an open or closed state. It acts as a gate, where fibers can wait for the latch to open before proceeding.

Details

A Latch can be in one of two states: open or closed. Fibers can:

  • Wait for the latch to open using await.
  • Proceed only when the latch is open using whenOpen.
  • Open the latch to release all waiting fibers using open.
  • Close the latch to block fibers using close.

Additionally, fibers can be released without changing the state of the latch using release.

Signature

export interface Latch extends Effect<void> {
  /**
   * Opens the latch, releasing all fibers waiting on it.
   *
   * **Details**
   *
   * Once the latch is opened, it remains open. Any fibers waiting on `await`
   * will be released and can continue execution.
   */
  readonly open: Effect<void>

  /**
   * Releases all fibers waiting on the latch without opening it.
   *
   * **Details**
   *
   * This function lets waiting fibers proceed without permanently changing the
   * state of the latch.
   */
  readonly release: Effect<void>

  /**
   * Waits for the latch to be opened.
   *
   * **Details**
   *
   * If the latch is already open, this effect completes immediately. Otherwise,
   * it suspends the fiber until the latch is opened.
   */
  readonly await: Effect<void>

  /**
   * Closes the latch, blocking fibers from proceeding.
   *
   * **Details**
   *
   * This operation puts the latch into a closed state, requiring it to be
   * reopened before waiting fibers can proceed.
   */
  readonly close: Effect<void>

  /**
   * Unsafely closes the latch, blocking fibers without effect guarantees.
   *
   * **Details**
   *
   * Use this operation cautiously, as it does not run within an effect context
   * and bypasses runtime guarantees.
   */
  readonly unsafeClose: () => void

  /**
   * Runs the given effect only when the latch is open.
   *
   * **Details**
   *
   * This function ensures that the provided effect executes only if the latch
   * is open. If the latch is closed, the fiber will wait until it opens.
   */
  readonly whenOpen: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>

  readonly [Unify.typeSymbol]?: unknown
  readonly [Unify.unifySymbol]?: LatchUnify<this>
  readonly [