Effect overview
Added in v2.0.0
Table of contents
- Caching
- Collecting
- Condition Checking
- Conditional Operators
- Config
- Console
- Context
- Converting Failures to Defects
- Creating Effects
- Do notation
- Error Accumulation
- Error handling
- Fallback
- Filtering
- Interruption
- Logging
- Looping
- Mapping
- Models
- Optional Wrapping
- Outcome Encapsulation
- Running Effects
- Scheduler
- Symbols
- Synchronization Utilities
- Tracing
- Type lambdas
- Zipping
- clock
- combining
- delays & timeouts
- fiber refs
- function
- getters & folding
- latch
- metrics
- models
- random
- repetition / recursion
- requests & batching
- runtime
- scoping, resources & finalization
- semaphore
- sequencing
- supervision & fibers
- utils
Caching
cached
Returns an effect that computes a result lazily and caches it. Subsequent evaluations of this effect will return the cached result without re-executing the logic.
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. Memoization ensures that results are stored and reused for the same inputs, reducing the need to recompute them.
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
Similar to {@link cachedWithTTL}, this function caches an effect’s result for a specified duration. It also includes an additional effect for manually invalidating the cached value before it naturally expires.
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 the timeToLive
. When the cache expires after the duration, the effect will be recomputed upon next evaluation.
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.
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
Collecting
all
Combines multiple effects into one, returning results based on the input structure.
When to Use
Use Effect.all
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
The Effect.all
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
Evaluate and run each effect in the structure and collect the results, discarding results from failed effects.
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>>
Added in v2.0.0
allWith
A data-last version of {@link all}, designed for use in pipelines.
When to Use
The allWith
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 all elements until the effectful predicate returns true.
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>
}
Added in v2.0.0
dropWhile
Drops all elements so long as the predicate returns true.
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>
}
Added in v2.0.0
findFirst
Returns the first element that satisfies the effectful predicate.
Signature
export declare const findFirst: {
<A, E, R>(
f: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
): (elements: Iterable<A>) => Effect<Option.Option<A>, E, R>
<A, E, R>(
elements: Iterable<A>,
f: (a: NoInfer<A>, i: number) => Effect<boolean, E, R>
): Effect<Option.Option<A>, E, R>
}
Added in v2.0.0
head
Returns a successful effect with the head of the collection if the collection is non-empty, or fails with the error None
if the collection is empty.
Signature
export declare const head: <A, E, R>(self: Effect<Iterable<A>, E, R>) => Effect<A, Cause.NoSuchElementException | E, R>
Added in v2.0.0
mergeAll
Merges an Iterable<Effect<A, E, R>>
to a single effect, working sequentially.
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>>
}
Added in v2.0.0
reduce
Folds an Iterable<A>
using an effectual function f, working sequentially from left to right.
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>
}
Added in v2.0.0
reduceEffect
Reduces an Iterable<Effect<A, E, R>>
to a single effect.
Signature
export declare const reduceEffect: {
<Z, E, R, Eff extends Effect<any, any, any>>(
zero: Effect<Z, E, R>,
f: (acc: 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: (acc: 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>>
}
Added in v2.0.0
reduceRight
Folds an Iterable<A>
using an effectual function f, working sequentially from left to right.
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>
}
Added in v2.0.0
reduceWhile
Folds over the elements in this chunk from the left, stopping the fold early when the predicate is not satisfied.
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>
}
Added in v2.0.0
replicateEffect
Performs this effect the specified number of times and collects the results.
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>
}
Added in v2.0.0
takeUntil
Takes elements until the effectual predicate returns true.
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>
}
Added in v2.0.0
takeWhile
Takes all elements so long as the effectual predicate returns true.
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>
}
Added in v2.0.0
Condition Checking
every
Determines whether all elements of the Collection<A>
satisfies the effectual predicate f
.
Signature
export declare const every: {
<A, E, R>(f: (a: A, i: number) => Effect<boolean, E, R>): (elements: Iterable<A>) => Effect<boolean, E, R>
<A, E, R>(elements: Iterable<A>, f: (a: A, i: number) => Effect<boolean, E, R>): Effect<boolean, E, R>
}
Added in v2.0.0
exists
Determines whether any element of the Iterable<A>
satisfies the effectual predicate f
.
Signature
export declare const exists: {
<A, E, R>(
f: (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>,
f: (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>
}
Added in v2.0.0
isEffect
This function returns true
if the specified value is an Effect
value, false
otherwise.
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 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
isFailure
Returns true
if this effect is a failure, false
otherwise.
Signature
export declare const isFailure: <A, E, R>(self: Effect<A, E, R>) => Effect<boolean, never, R>
Added in v2.0.0
isSuccess
Returns true
if this effect is a success, false
otherwise.
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.
when
allows you to conditionally execute an effect, similar to using an if (condition)
expression, but with the added benefit of handling effects. If the condition is true
, the effect is executed; otherwise, it does nothing.
The result of the effect is wrapped in an Option<A>
to indicate whether the effect was executed. If the condition is true
, the result of the effect is wrapped in a Some
. If the condition is false
, the result is None
, representing that the effect was skipped.
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
Executes an effect conditionally, based on the result of another effect.
Use whenEffect
when the condition to determine whether to execute the effect depends on the outcome of another effect that produces a boolean value.
If the condition effect evaluates to true
, the specified effect is executed. If it evaluates to false
, no effect is executed.
The result of the effect is wrapped in an Option<A>
to indicate whether the effect was executed. If the condition is true
, the result of the effect is wrapped in a Some
. If the condition is false
, the result is None
, representing that the effect was skipped.
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 this workflow when value of the specified FiberRef
satisfies the predicate.
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 this workflow when the value of the Ref
satisfies the predicate.
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
Retrieves the default config provider, and passes it to the specified function, which may return an effect that uses the provider to perform some work or compute some value.
Signature
export declare const configProviderWith: <A, E, R>(
f: (configProvider: ConfigProvider) => Effect<A, E, R>
) => Effect<A, E, R>
Added in v2.0.0
withConfigProvider
Executes the specified workflow with the specified configuration provider.
Signature
export declare const withConfigProvider: {
(value: ConfigProvider): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R>(effect: Effect<A, E, R>, value: ConfigProvider): Effect<A, E, R>
}
Added in v2.0.0
withConfigProviderScoped
Sets the configuration provider to the specified value and restores it to its original value when the scope is closed.
Signature
export declare const withConfigProviderScoped: (value: 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
Signature
export declare const Service: <Self>() => {
<
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
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, Layer } from "effect"
class MapTag extends Effect.Tag("MapTag")<MapTag, Map<string, string>>() {
static Live = Layer.effect(
this,
Effect.sync(() => new Map())
)
}
Added in v2.0.0
context
Signature
export declare const context: <R>() => Effect<Context.Context<R>, never, R>
Added in v2.0.0
contextWith
Accesses the context of 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
Effectually accesses the context of the effect.
Signature
export declare const contextWithEffect: <R0, A, E, R>(
f: (context: Context.Context<R0>) => Effect<A, E, R>
) => Effect<A, E, R | R0>
Added in v2.0.0
mapInputContext
Provides some of the context required to run this effect, leaving the remainder R0
.
Signature
export declare const mapInputContext: {
<R0, R>(f: (context: Context.Context<R0>) => Context.Context<R>): <A, E>(self: Effect<A, E, R>) => Effect<A, E, R0>
<A, E, R, R0>(self: Effect<A, E, R>, f: (context: Context.Context<R0>) => Context.Context<R>): Effect<A, E, R0>
}
Added in v2.0.0
provide
Provides the necessary Layer
s to an effect, removing its dependency on the environment.
You can pass multiple layers, a Context
, Runtime
, or ManagedRuntime
to the effect.
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
The provideService
function is used to provide an actual implementation for a service in the context of an effect.
This function allows you to associate a service with its implementation so that it can be used in your program. You define the service (e.g., a random number generator), and then you use provideService
to link that service to its implementation. Once the implementation is provided, the effect can be run successfully without further requirements.
Signature
export declare const provideService: {
<T extends Context.Tag<any, any>>(
tag: T,
service: Context.Tag.Service<T>
): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, Exclude<R, Context.Tag.Identifier<T>>>
<A, E, R, T extends Context.Tag<any, any>>(
self: Effect<A, E, R>,
tag: T,
service: Context.Tag.Service<T>
): Effect<A, E, Exclude<R, Context.Tag.Identifier<T>>>
}
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
Provides the effect with the single service it requires. If the effect requires more than one service use provide
instead.
Signature
export declare const provideServiceEffect: {
<T extends Context.Tag<any, any>, E1, R1>(
tag: T,
effect: Effect<Context.Tag.Service<T>, E1, R1>
): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E1 | E, R1 | Exclude<R, Context.Tag.Identifier<T>>>
<A, E, R, T extends Context.Tag<any, any>, E1, R1>(
self: Effect<A, E, R>,
tag: T,
effect: Effect<Context.Tag.Service<T>, E1, R1>
): Effect<A, E | E1, R1 | Exclude<R, Context.Tag.Identifier<T>>>
}
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
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
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
Signature
export declare const serviceOption: <I, S>(tag: Context.Tag<I, S>) => Effect<Option.Option<S>>
Added in v2.0.0
serviceOptional
Signature
export declare const serviceOptional: <I, S>(tag: Context.Tag<I, S>) => Effect<S, Cause.NoSuchElementException>
Added in v2.0.0
updateService
Updates the service with the required service entry.
Signature
export declare const updateService: {
<T extends Context.Tag<any, any>>(
tag: T,
f: (service: Context.Tag.Service<T>) => Context.Tag.Service<T>
): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R | Context.Tag.Identifier<T>>
<A, E, R, T extends Context.Tag<any, any>>(
self: Effect<A, E, R>,
tag: T,
f: (service: Context.Tag.Service<T>) => Context.Tag.Service<T>
): Effect<A, E, R | Context.Tag.Identifier<T>>
}
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.
*When to Use
Use orDie
when failures should be treated as unrecoverable defects and no error handling is required.
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.
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.
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.
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.
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.
When to Use
Use async
when dealing with APIs that use callback-style instead of async/await
or Promise
.
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 theFiber
executing thisEffect
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.
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.
When to Use
Use die
when encountering unexpected conditions in your code that should not be handled as regular errors but instead represent unrecoverable defects.
Details
The die
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.
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.
When to Use
Use dieMessage
when you want to terminate a fiber due to an unrecoverable defect and include a clear explanation in the message.
Details
The dieMessage
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.
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.
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
Signature
export declare const failCause: <E>(cause: Cause.Cause<E>) => Effect<never, E>
Added in v2.0.0
failCauseSync
Signature
export declare const failCauseSync: <E>(evaluate: LazyArg<Cause.Cause<E>>) => Effect<never, E>
Added in v2.0.0
failSync
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
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
Returns an effect that will never produce anything. The moral equivalent of while(true) {}
, only without the wasted CPU cycles.
Signature
export declare const never: Effect<never, never, never>
Added in v2.0.0
none
Requires the option produced by this value to be None
.
Signature
export declare const none: <A, E, R>(
self: Effect<Option.Option<A>, E, R>
) => Effect<void, E | Cause.NoSuchElementException, R>
Added in v2.0.0
promise
Creates an Effect
that represents an asynchronous computation guaranteed to succeed.
When to Use
Use promise
when you are sure the operation will not reject.
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.
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
.
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.
When to Use
Use suspend
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.
Details
suspend
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.
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.
When to Use
Use sync
when you are sure the operation will not fail.
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}.
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
:
- If you don’t provide a
catch
function, the error is caught and the effect fails with anUnknownException
. - If you provide a
catch
function, the error is caught and thecatch
function maps it to an error of typeE
.
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
:
- If you don’t provide a
catch
function, the error is caught and the effect fails with anUnknownException
. - If you provide a
catch
function, the error is caught and thecatch
function maps it to an error of typeE
.
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
Signature
export declare const void: Effect<void, never, never>
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: <A extends Clock.Clock>(value: A) => Effect<void, never, Scope.Scope>
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
withRandomScoped
Sets the implementation of the random service to the specified value and restores it to its original value when the scope is closed.
Signature
export declare const withRandomScoped: <A extends Random.Random>(value: A) => Effect<void, never, Scope.Scope>
Added in v2.0.0
yieldNow
Signature
export declare const yieldNow: (options?: { readonly priority?: number | undefined }) => Effect<void>
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:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEffect
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - 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:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEffect
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - 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:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEffect
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - 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:
- Start the do simulation using the
Do
value - Within the do simulation scope, you can use the
bind
function to define variables and bind them toEffect
values - You can accumulate multiple
bind
statements to define multiple variables within the scope - 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
The partition
function processes an iterable and applies an effectful function to each element, categorizing the results into successes and failures.
This function returns a tuple where the first part contains all the failures and the second part contains all the successes. It’s useful when you need to separate successful outcomes from failures, allowing you to handle them differently. The function allows the entire collection to be processed without halting on failures, and failures are collected in a separate list while the 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
The validate
function allows you to combine multiple effects, continuing the combination even if some of the effects fail. It accumulates both successes and failures, allowing you to proceed through all effects regardless of individual failures.
This function is similar to {@link zip}, but with validate
, errors do not stop the execution of subsequent effects. Instead, errors are accumulated in a Cause
and reported in the final result. This is useful when you want to collect all results, including failures, instead of stopping at the first error.
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
The validateAll
function allows you to apply an effectful operation to each element of a collection, while collecting both the successes and failures. Unlike {@link forEach}, which would stop at the first error, validateAll
continues processing all elements, accumulating both successes and failures.
This function transforms all elements of the collection using the provided effectful operation. If any elements fail, the errors are captured and included in the result, alongside the successful results. However, if there are any errors, all successes are lost in the final result, which is an important consideration when using this function.
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>, Array<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, 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 discard?: false | undefined
readonly concurrentFinalizers?: boolean | undefined
}
| undefined
): Effect<Array<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 discard: true
readonly concurrentFinalizers?: boolean | undefined
}
): Effect<void, Array<E>, R>
}
Example
import { Effect, Console } from "effect"
// ┌─── Effect<number[], 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
The validateFirst
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.
This function processes a collection of elements and applies an effectful operation to each. Unlike validateAll
, which accumulates both successes and failures, 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 zips this effect with the specified effect using the specified combiner function. Combines the causes in case both effect fail.
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 specified error.
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>; }
Added in v2.0.0
catchAll
Handles all errors in an effect by providing a fallback effect.
Details
The catchAll
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: catchAll
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 some or all of the error cases with provided cause.
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
The cause
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.
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
Returns an effect that ignores errors and runs repeatedly until it eventually succeeds.
Signature
export declare const eventually: <A, E, R>(self: Effect<A, E, R>) => Effect<A, never, R>
Added in v2.0.0
ignore
Discards both the success and failure values of an effect.
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
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
Returns a new effect that ignores the success or failure of this effect, but which also logs failures at the Debug level, just in case the failure turns out to be important.
Signature
export declare const ignoreLogged: <A, E, R>(self: Effect<A, E, R>) => Effect<void, never, R>
Added in v2.0.0
parallelErrors
The parallelErrors
function captures all failure errors from concurrent operations and combines them into a single error in the error channel.
This function is useful when you are running multiple operations concurrently and you want to gather all the errors that occur. Instead of handling each error separately, parallelErrors
consolidates them into one, making it easier to manage and respond to errors from multiple operations at once.
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.
The retry
function allows you to retry a failing effect multiple times according to a specified policy. 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.
The retry
function takes an effect and a 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.
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
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!
Added in v2.0.0
retryOrElse
Retries a failing effect and runs a fallback effect if retries are exhausted.
The retryOrElse
function attempts to retry a failing effect multiple times according to a defined retry policy. If the retries are exhausted and the effect still fails, it runs a fallback effect instead. 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
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, () => 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
The sandbox
function transforms an effect by exposing the full cause of any error, defect, or fiber interruption that might occur during its execution. It changes the error channel of the effect to include detailed information about the cause, which is wrapped in a Cause<E>
type.
This function is useful when you need access to the complete underlying cause of failures, defects, or interruptions, enabling more detailed error handling. Once you apply sandbox
, you can use operators like {@link catchAll} and {@link catchTags} to handle specific error conditions. If necessary, you can revert the sandboxing operation with {@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 whose success is mapped by the specified side effecting try
function, translating any promise rejections into typed failed effects via 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 whose success is mapped by the specified side effecting try
function, translating any promise rejections into typed failed effects via 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 series of effects and returns the result of the first successful one. If none of the effects succeed, it fails with the error from the last effect.
firstSuccessOf
allows you to try multiple effects in sequence, and as soon as one of them succeeds, it returns that result. If all effects fail, it returns the error of the last effect in the list. This is useful when you have several potential alternatives and want to use the first one that works.
This function is sequential, meaning that the Effect
values in the iterable will be executed in sequence, and the first one that succeeds will determine the outcome of the resulting Effect
value.
Important: If the collection of effects provided to firstSuccessOf
is empty, it will throw an IllegalArgumentException
error.
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
Tries one effect, and if it fails, attempts another effect as a fallback.
orElse
allows you to attempt to run an effect, and if it fails, you can provide a fallback effect to run instead. This is useful for handling failures gracefully by defining an alternative effect to execute if the first one encounters an error.
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 original failure with a new failure value.
orElseFail
allows you to replace the failure from one effect with a custom failure value. If the effect fails, you can provide a new failure to be returned instead of the original one.
Important: This function only applies to failed effects. If the effect succeeds, it will remain unaffected.
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
Replaces the original failure with a success value, ensuring the effect cannot fail.
orElseSucceed
allows you to replace the failure of an effect with a success value. If the effect fails, it will instead succeed with the provided value, ensuring the effect always completes successfully. This is useful when you want to guarantee a successful result regardless of whether the original effect failed.
The function ensures that any failure is effectively “swallowed” and replaced by a successful value, which can be helpful for providing default values in case of failure.
Important: This function only applies to failed effects. If the effect already succeeds, it will remain unchanged.
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
Filtering
filter
Filters the collection using the specified effectful predicate.
Signature
export declare const filter: {
<A, E, R>(
f: (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>,
f: (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>
}
Added in v2.0.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
Filter the specified effect with the provided function, dying with specified defect if the predicate fails.
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
Filter the specified effect with the provided function, dying with specified message if the predicate fails.
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 the specified effect with the provided function returning the value of the effect if it is successful, otherwise returns the value of orElse
.
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
Filter the specified effect with the provided function, failing with specified error if the predicate fails.
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
Interruption
allowInterrupt
This function checks if any fibers are attempting to interrupt the current fiber, and if so, performs self-interruption.
Note that this allows for interruption to occur in uninterruptible regions.
Signature
export declare const allowInterrupt: Effect<void, never, never>
Added in v2.0.0
checkInterruptible
Checks the interrupt status, and produces the effect returned by the specified callback.
Signature
export declare const checkInterruptible: <A, E, R>(f: (isInterruptible: boolean) => Effect<A, E, R>) => Effect<A, E, R>
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.
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
Signature
export declare const interrupt: Effect<never, never, never>
Added in v2.0.0
interruptWith
Signature
export declare const interruptWith: (fiberId: FiberId.FiberId) => Effect<never>
Added in v2.0.0
interruptible
Signature
export declare const interruptible: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
Added in v2.0.0
interruptibleMask
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
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>
}
Added in v2.0.0
uninterruptible
Signature
export declare const uninterruptible: <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
Added in v2.0.0
uninterruptibleMask
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
Logging
annotateLogs
Augments log outputs by appending custom annotations to log entries generated within an effect. This function provides a way to add more context and detail to log messages, making them more informative and easier to trace.
Signature
export declare const annotateLogs: {
(key: string, value: unknown): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
(values: Record<string, unknown>): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R>(effect: Effect<A, E, R>, key: string, value: unknown): Effect<A, E, R>
<A, E, R>(effect: Effect<A, E, R>, values: Record<string, unknown>): Effect<A, E, R>
}
Example
import { Effect } from "effect"
const program = Effect.gen(function* () {
yield* Effect.log("message1")
yield* Effect.log("message2")
}).pipe(Effect.annotateLogs("key", "value")) // Annotation as key/value pair
// Effect.runFork(program)
// timestamp=... level=INFO fiber=#0 message=message1 key=value
// timestamp=... level=INFO fiber=#0 message=message2 key=value
Added in v2.0.0
annotateLogsScoped
Applies log annotations with a limited scope, restricting their appearance to specific sections of your effect computations. Use annotateLogsScoped
to add metadata to logs that only appear within a defined Scope
, making it easier to manage context-specific logging.
Signature
export declare const annotateLogsScoped: {
(key: string, value: unknown): Effect<void, never, Scope.Scope>
(values: Record<string, unknown>): Effect<void, never, Scope.Scope>
}
Example
import { Effect } from "effect"
const program = Effect.gen(function* () {
yield* Effect.log("no annotations")
yield* Effect.annotateLogsScoped({ key: "value" })
yield* Effect.log("message1") // Annotation is applied to this log
yield* Effect.log("message2") // Annotation is applied to this log
}).pipe(Effect.scoped, Effect.andThen(Effect.log("no annotations again")))
// Effect.runFork(program)
// timestamp=... level=INFO fiber=#0 message="no annotations"
// timestamp=... level=INFO fiber=#0 message=message1 key=value
// timestamp=... level=INFO fiber=#0 message=message2 key=value
// timestamp=... level=INFO fiber=#0 message="no annotations again"
Added in v3.1.0
log
Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using Cause
instances.
To adjust the log level, use the Logger.withMinimumLogLevel
function.
Signature
export declare const log: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Example
import { Cause, Effect } from "effect"
const program = Effect.log("message1", "message2", Cause.die("Oh no!"), Cause.die("Oh uh!"))
// Effect.runFork(program)
// Output:
// timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no!
// Error: Oh uh!"
Added in v2.0.0
logAnnotations
Retrieves the log annotations associated with the current scope.
Signature
export declare const logAnnotations: Effect<HashMap.HashMap<string, unknown>, never, never>
Added in v2.0.0
logDebug
Logs the specified messages at the DEBUG log level. DEBUG messages are not shown by default.
To view DEBUG messages, adjust the logging settings using Logger.withMinimumLogLevel
and set the log level to LogLevel.Debug
.
Signature
export declare const logDebug: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Example
import { Effect, Logger, LogLevel } from "effect"
const program = Effect.logDebug("message1").pipe(Logger.withMinimumLogLevel(LogLevel.Debug))
// Effect.runFork(program)
// timestamp=... level=DEBUG fiber=#0 message=message1
Added in v2.0.0
logError
Logs the specified message or cause at the Error log level.
Signature
export declare const logError: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Added in v2.0.0
logFatal
Logs the specified message or cause at the Fatal log level.
Signature
export declare const logFatal: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Added in v2.0.0
logInfo
Logs the specified message or cause at the Info log level.
Signature
export declare const logInfo: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Added in v2.0.0
logTrace
Logs the specified message or cause at the Trace log level.
Signature
export declare const logTrace: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Added in v2.0.0
logWarning
Logs the specified message or cause at the Warning log level.
Signature
export declare const logWarning: (...message: ReadonlyArray<any>) => Effect<void, never, never>
Added in v2.0.0
logWithLevel
Logs the specified message or cause at the specified log level.
Signature
export declare const logWithLevel: (level: LogLevel, ...message: ReadonlyArray<any>) => Effect<void>
Added in v2.0.0
withLogSpan
Adds a log span to your effects, which tracks and logs the duration of operations or tasks. This is useful for performance monitoring and debugging time-sensitive processes.
Signature
export declare const withLogSpan: {
(label: string): <A, E, R>(effect: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R>(effect: Effect<A, E, R>, label: string): Effect<A, E, R>
}
Example
import { Effect } from "effect"
const program = Effect.gen(function* () {
yield* Effect.sleep("1 second")
yield* Effect.log("The job is finished!")
}).pipe(Effect.withLogSpan("myspan"))
// Effect.runFork(program)
// timestamp=... level=INFO fiber=#0 message="The job is finished!" myspan=1011ms
Added in v2.0.0
withUnhandledErrorLogLevel
Decides wether child fibers will report or not unhandled errors via the logger
Signature
export declare const withUnhandledErrorLogLevel: {
(level: Option.Option<LogLevel>): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R>(self: Effect<A, E, R>, level: Option.Option<LogLevel>): Effect<A, E, R>
}
Added in v2.0.0
Looping
forEach
Executes an effectful operation for each element in an Iterable
.
Details
The forEach
function applies a provided operation to each element in the iterable, producing a new effect that returns an array of results.
If any effect fails, the iteration stops immediately (short-circuiting), and the error is propagated.
Concurrency
The concurrency
option controls how many operations are performed concurrently. By default, the operations are performed sequentially.
Discarding Results
If the discard
option is set to true
, the intermediate results are not collected, and the final result of the operation is void
.
Signature
export declare const forEach: {
<B, E, R, S extends Iterable<any>>(
f: (a: RA.ReadonlyArray.Infer<S>, 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
): (self: S) => Effect<RA.ReadonlyArray.With<S, B>, 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
}
): (self: Iterable<A>) => Effect<void, E, R>
<B, E, R, S extends Iterable<any>>(
self: S,
f: (a: RA.ReadonlyArray.Infer<S>, 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<RA.ReadonlyArray.With<S, B>, E, R>
<A, B, E, R>(
self: 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, E, R>
}
Example
// Title: Applying Effects to Iterable Elements
import { Effect, Console } from "effect"
const result = Effect.forEach([1, 2, 3, 4, 5], (n, index) =>
Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2))
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// [ 2, 4, 6, 8, 10 ]
Example
// Title: Using discard to Ignore Results
import { Effect, Console } from "effect"
// Apply effects but discard the results
const result = Effect.forEach(
[1, 2, 3, 4, 5],
(n, index) => Console.log(`Currently at index ${index}`).pipe(Effect.as(n * 2)),
{ discard: true }
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at index 0
// Currently at index 1
// Currently at index 2
// Currently at index 3
// Currently at index 4
// undefined
Added in v2.0.0
iterate
Repeatedly updates a state through an effectful operation, running the body
effect to update the state in each iteration. It continues iterating as long as the while
condition evaluates to true
.
This function works like a while
loop in JavaScript but with effectful operations:
let result = initial
while (options.while(result)) {
result = options.body(result)
}
return result
Signature
export declare const iterate: {
<A, B extends A, R, E>(
initial: A,
options: { readonly while: Refinement<A, B>; readonly body: (b: B) => Effect<A, E, R> }
): Effect<A, E, R>
<A, R, E>(
initial: A,
options: { readonly while: Predicate<A>; readonly body: (a: A) => Effect<A, E, R> }
): Effect<A, E, R>
}
Example
// Title: Effectful Iteration
import { Effect } from "effect"
const result = Effect.iterate(
// Initial result
1,
{
// Condition to continue iterating
while: (result) => result <= 5,
// Operation to change the result
body: (result) => Effect.succeed(result + 1)
}
)
Effect.runPromise(result).then(console.log)
// Output: 6
Added in v2.0.0
loop
Repeatedly updates a state using a step
function until a condition, defined by the while
function, becomes false
. It collects the intermediate states in an array and returns them as the final result. The loop executes effectful operations at each iteration.
This function is similar to a while
loop in JavaScript, with the addition of effectful computations:
let state = initial
const result = []
while (options.while(state)) {
result.push(options.body(state)) // Perform the effectful operation
state = options.step(state) // Update the state
}
return result
Discarding Intermediate Results
If the discard
option is set to true
, the intermediate results are discarded, and the final result will be void
.
Signature
export declare const loop: {
<A, B extends A, C, E, R>(
initial: A,
options: {
readonly while: Refinement<A, B>
readonly step: (b: B) => A
readonly body: (b: B) => Effect<C, E, R>
readonly discard?: false | undefined
}
): Effect<Array<C>, E, R>
<A, C, E, R>(
initial: A,
options: {
readonly while: (a: A) => boolean
readonly step: (a: A) => A
readonly body: (a: A) => Effect<C, E, R>
readonly discard?: false | undefined
}
): Effect<Array<C>, E, R>
<A, B extends A, C, E, R>(
initial: A,
options: {
readonly while: Refinement<A, B>
readonly step: (b: B) => A
readonly body: (b: B) => Effect<C, E, R>
readonly discard: true
}
): Effect<void, E, R>
<A, C, E, R>(
initial: A,
options: {
readonly while: (a: A) => boolean
readonly step: (a: A) => A
readonly body: (a: A) => Effect<C, E, R>
readonly discard: true
}
): Effect<void, E, R>
}
Example
// Title: Looping with Collected Results
import { Effect } from "effect"
// A loop that runs 5 times, collecting each iteration's result
const result = Effect.loop(
// Initial state
1,
{
// Condition to continue looping
while: (state) => state <= 5,
// State update function
step: (state) => state + 1,
// Effect to be performed on each iteration
body: (state) => Effect.succeed(state)
}
)
Effect.runPromise(result).then(console.log)
// Output: [1, 2, 3, 4, 5]
Example
// Title: Loop with Discarded Results
import { Effect, Console } from "effect"
const result = Effect.loop(
// Initial state
1,
{
// Condition to continue looping
while: (state) => state <= 5,
// State update function
step: (state) => state + 1,
// Effect to be performed on each iteration
body: (state) => Console.log(`Currently at state ${state}`),
// Discard intermediate results
discard: true
}
)
Effect.runPromise(result).then(console.log)
// Output:
// Currently at state 1
// Currently at state 2
// Currently at state 3
// Currently at state 4
// Currently at state 5
// undefined
Added in v2.0.0
Mapping
as
Replaces the value inside an effect with a constant value.
as
allows you to ignore the original value inside an effect and replace it with a new constant value.
Signature
export declare const as: {
<B>(value: B): <A, E, R>(self: Effect<A, E, R>) => Effect<B, E, R>
<A, E, R, B>(self: Effect<A, E, R>, value: B): Effect<B, E, R>
}
Example
// Title: Replacing a Value
import { pipe, Effect } from "effect"
// Replaces the value 5 with the constant "new value"
const program = pipe(Effect.succeed(5), Effect.as("new value"))
Effect.runPromise(program).then(console.log)
// Output: "new value"
Added in v2.0.0
asSome
This function maps the success value of an Effect
value to a Some
value in an Option
value. If the original Effect
value fails, the returned Effect
value will also fail.
Signature
export declare const asSome: <A, E, R>(self: Effect<A, E, R>) => Effect<Option.Option<A>, E, R>
Added in v2.0.0
asSomeError
This function maps the error value of an Effect
value to a Some
value in an Option
value. If the original Effect
value succeeds, the returned Effect
value will also succeed.
Signature
export declare const asSomeError: <A, E, R>(self: Effect<A, E, R>) => Effect<A, Option.Option<E>, R>
Added in v2.0.0
asVoid
This function maps the success value of an Effect
value to void
. If the original Effect
value succeeds, the returned Effect
value will also succeed. If the original Effect
value fails, the returned Effect
value will fail with the same error.
Signature
export declare const asVoid: <A, E, R>(self: Effect<A, E, R>) => Effect<void, E, R>
Added in v2.0.0
flip
The flip
function swaps the success and error channels of an effect, so that the success becomes the error, and the error becomes the success.
This function is useful when you need to reverse the flow of an effect, treating the previously successful values as errors and vice versa. This can be helpful in scenarios where you want to handle a success as a failure or treat an error as a valid result.
Signature
export declare const flip: <A, E, R>(self: Effect<A, E, R>) => Effect<E, A, R>
Example
import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const program = Effect.fail("Oh uh!").pipe(Effect.as(2))
// ┌─── Effect<string, number, never>
// ▼
const flipped = Effect.flip(program)
Added in v2.0.0
flipWith
Swaps the error/value parameters, applies the function f
and flips the parameters back
Signature
export declare const flipWith: {
<E, A, R, E2, A2, R2>(
f: (effect: Effect<E, A, R>) => Effect<E2, A2, R2>
): (self: Effect<A, E, R>) => Effect<A2, E2, R2>
<A, E, R, E2, A2, R2>(self: Effect<A, E, R>, f: (effect: Effect<E, A, R>) => Effect<E2, A2, R2>): Effect<A2, E2, R2>
}
Added in v2.0.0
map
Transforms the value inside an effect by applying a function to it.
Syntax
const mappedEffect = pipe(myEffect, Effect.map(transformation))
// or
const mappedEffect = Effect.map(myEffect, transformation)
// or
const mappedEffect = myEffect.pipe(Effect.map(transformation))
Details
map
takes a function and applies it to the value contained within an effect, creating a new effect with the transformed value.
It’s important to note that effects are immutable, meaning that the original effect is not modified. Instead, a new effect is returned with the updated value.
Signature
export declare const map: {
<A, B>(f: (a: A) => B): <E, R>(self: Effect<A, E, R>) => Effect<B, E, R>
<A, E, R, B>(self: Effect<A, E, R>, f: (a: A) => B): Effect<B, E, R>
}
Example
// Title: Adding a Service Charge
import { pipe, Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(fetchTransactionAmount, Effect.map(addServiceCharge))
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
Added in v2.0.0
mapAccum
Applies a stateful transformation to each element of a collection, producing new elements along with an updated state.
When to Use
Use mapAccum
when you need to process each element of a collection while keeping track of some state across iterations.
Details
mapAccum
takes an initial state (initial
) and a function (f
) that is applied to each element. This function returns a new state and a transformed element. The final effect produces both the accumulated state and the transformed collection.
If the input collection is a non-empty array, the return type will match the input collection type.
Signature
export declare const mapAccum: {
<S, A, B, E, R, I extends Iterable<A> = Iterable<A>>(
initial: S,
f: (state: S, a: RA.ReadonlyArray.Infer<I>, i: number) => Effect<readonly [S, B], E, R>
): (elements: I) => Effect<[S, RA.ReadonlyArray.With<I, B>], E, R>
<A, S, B, E, R, I extends Iterable<A> = Iterable<A>>(
elements: I,
initial: S,
f: (state: S, a: RA.ReadonlyArray.Infer<I>, i: number) => Effect<readonly [S, B], E, R>
): Effect<[S, RA.ReadonlyArray.With<I, B>], E, R>
}
Example
import { Effect } from "effect"
// Define an initial state and a transformation function
const initialState = 0
const transformation = (state: number, element: string) =>
Effect.succeed<[number, string]>([state + element.length, element.toUpperCase()])
// Apply mapAccum to transform an array of strings
const program = Effect.mapAccum(["a", "bb", "ccc"], initialState, transformation)
Effect.runPromise(program).then(([finalState, transformedCollection]) => {
console.log(finalState)
console.log(transformedCollection)
})
// Output:
// 6
// [ 'A', 'BB', 'CCC' ]
Added in v2.0.0
mapBoth
The mapBoth
function allows you to apply transformations to both the error and success channels of an effect.
This function takes two map functions as arguments: one for the error channel and one for the success channel. You can use it when you want to modify both the error and the success values without altering the overall success or failure status of the effect.
Signature
export declare const mapBoth: {
<E, E2, A, A2>(options: {
readonly onFailure: (e: E) => E2
readonly onSuccess: (a: A) => A2
}): <R>(self: Effect<A, E, R>) => Effect<A2, E2, R>
<A, E, R, E2, A2>(
self: Effect<A, E, R>,
options: { readonly onFailure: (e: E) => E2; readonly onSuccess: (a: A) => A2 }
): Effect<A2, E2, R>
}
Example
import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const simulatedTask = Effect.fail("Oh no!").pipe(Effect.as(1))
// ┌─── Effect<boolean, Error, never>
// ▼
const modified = Effect.mapBoth(simulatedTask, {
onFailure: (message) => new Error(message),
onSuccess: (n) => n > 0
})
Added in v2.0.0
mapError
The mapError
function is used to transform or modify the error produced by an effect, without affecting its success value.
This function is helpful when you want to enhance the error with additional information, change the error type, or apply custom error handling while keeping the original behavior of the effect’s success values intact. It only operates on the error channel and leaves the success channel unchanged.
Signature
export declare const mapError: {
<E, E2>(f: (e: E) => E2): <A, R>(self: Effect<A, E, R>) => Effect<A, E2, R>
<A, E, R, E2>(self: Effect<A, E, R>, f: (e: E) => E2): Effect<A, E2, R>
}
Example
import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const simulatedTask = Effect.fail("Oh no!").pipe(Effect.as(1))
// ┌─── Effect<number, Error, never>
// ▼
const mapped = Effect.mapError(simulatedTask, (message) => new Error(message))
Added in v2.0.0
mapErrorCause
Returns an effect with its full cause of failure mapped using the specified function. This can be used to transform errors while preserving the original structure of Cause
.
See sandbox
, catchAllCause
for other functions for dealing with defects.
Signature
export declare const mapErrorCause: {
<E, E2>(f: (cause: Cause.Cause<E>) => Cause.Cause<E2>): <A, R>(self: Effect<A, E, R>) => Effect<A, E2, R>
<A, E, R, E2>(self: Effect<A, E, R>, f: (cause: Cause.Cause<E>) => Cause.Cause<E2>): Effect<A, E2, R>
}
Added in v2.0.0
merge
The merge
function combines both the error and success channels of an effect, creating a new effect that never fails.
This function transforms an effect that may fail into one that always returns a value, where both success and failure outcomes are handled as values in the success channel. This can be useful when you want to continue execution regardless of the error type and still capture both successful results and errors as part of the outcome.
Signature
export declare const merge: <A, E, R>(self: Effect<A, E, R>) => Effect<E | A, never, R>
Example
import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const program = Effect.fail("Oh uh!").pipe(Effect.as(2))
// ┌─── Effect<number | string, never, never>
// ▼
const recovered = Effect.merge(program)
Added in v2.0.0
negate
Returns a new effect where boolean value of this effect is negated.
Signature
export declare const negate: <E, R>(self: Effect<boolean, E, R>) => Effect<boolean, E, R>
Added in v2.0.0
Models
Adapter (interface)
Signature
export interface Adapter {
<A, E, R>(self: Effect<A, E, R>): Effect<A, E, R>
<A, _A, _E, _R>(a: A, ab: (a: A) => Effect<_A, _E, _R>): Effect<_A, _E, _R>
<A, B, _A, _E, _R>(a: A, ab: (a: A) => B, bc: (b: B) => Effect<_A, _E, _R>): Effect<_A, _E, _R>
<A, B, C, _A, _E, _R>(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => Effect<_A, _E, _R>): Effect<_A, _E, _R>
<A, B, C, D, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (g: H) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => O,
op: (o: O) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => O,
op: (o: O) => P,
pq: (p: P) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => O,
op: (o: O) => P,
pq: (p: P) => Q,
qr: (q: Q) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => O,
op: (o: O) => P,
pq: (p: P) => Q,
qr: (q: Q) => R,
rs: (r: R) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg: (f: F) => G,
gh: (g: G) => H,
hi: (h: H) => I,
ij: (i: I) => J,
jk: (j: J) => K,
kl: (k: K) => L,
lm: (l: L) => M,
mn: (m: M) => N,
no: (n: N) => O,
op: (o: O) => P,
pq: (p: P) => Q,
qr: (q: Q) => R,
rs: (r: R) => S,
st: (s: S) => Effect<_A, _E, _R>
): Effect<_A, _E, _R>
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, _A, _E, _R>(
a: A,
ab: (a: A) => B,
bc: (b: B) => C,
cd: (c: C) => D,
de: (d: D) => E,
ef: (e: E) => F,
fg