Skip to content

Schedule Combinators

Schedules define stateful, possibly effectful, recurring schedules of events, and compose in a variety of ways. Combinators allow us to take schedules and combine them together to get other schedules.

To demonstrate the functionality of different schedules, we will use the following helper function that logs the delay between executions.

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
27 collapsed lines
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}

Schedules can be composed in different ways:

ModeDescription
UnionCombines two schedules and recurs if either schedule wants to continue, using the shorter delay.
IntersectionCombines two schedules and recurs only if both schedules want to continue, using the longer delay.
SequencingCombines two schedules by running the first one fully, then switching to the second.

Combines two schedules using union. The schedule recurs as long as one of the schedules wants to, using the minimum delay between recurrences.

Example (Union of Exponential and Spaced Schedules)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<[Duration, number], unknown, never>
schedule
=
import Schedule
Schedule
.
const union: <Duration, unknown, never, number, unknown, never>(self: Schedule.Schedule<Duration, unknown, never>, that: Schedule.Schedule<number, unknown, never>) => Schedule.Schedule<[Duration, number], unknown, never> (+1 overload)

Returns a new schedule that performs a geometric union on the intervals defined by both schedules.

@since2.0.0

union
(
import Schedule
Schedule
.
const exponential: (base: DurationInput, factor?: number) => Schedule.Schedule<Duration>

A schedule that always recurs, but will wait a certain amount between repetitions, given by base * factor.pow(n), where n is the number of repetitions so far. Returns the current duration between recurrences.

@since2.0.0

exponential
("100 millis"),
import Schedule
Schedule
.
const spaced: (duration: DurationInput) => Schedule.Schedule<number>

Returns a schedule that recurs continuously, each repetition spaced the specified duration from the last run.

@since2.0.0

spaced
("1 second")
)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, [Duration, number]>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<[Duration, number], void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<[Duration, number], unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 100 < exponential
#2 delay: 200
#3 delay: 400
#4 delay: 800
#5 delay: 1000 < spaced
#6 delay: 1000
#7 delay: 1000
#8 delay: 1000
#9 delay: 1000
...
*/

When we use the combined schedule with Effect.repeat, we observe that the effect is executed repeatedly based on the minimum delay between the two schedules. In this case, the delay alternates between the exponential schedule (increasing delay) and the spaced schedule (constant delay).

Combines two schedules using intersection. The schedule recurs only if both schedules want to continue, using the maximum delay between them.

Example (Intersection of Exponential and Recurs Schedules)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<[Duration, number], unknown, never>
schedule
=
import Schedule
Schedule
.
const intersect: <Duration, unknown, never, number, unknown, never>(self: Schedule.Schedule<Duration, unknown, never>, that: Schedule.Schedule<number, unknown, never>) => Schedule.Schedule<[Duration, number], unknown, never> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const exponential: (base: DurationInput, factor?: number) => Schedule.Schedule<Duration>

A schedule that always recurs, but will wait a certain amount between repetitions, given by base * factor.pow(n), where n is the number of repetitions so far. Returns the current duration between recurrences.

@since2.0.0

exponential
("10 millis"),
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(5)
)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, [Duration, number]>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<[Duration, number], void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<[Duration, number], unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 10 < exponential
#2 delay: 20
#3 delay: 40
#4 delay: 80
#5 delay: 160
(end) < recurs
*/

When we use the combined schedule with Effect.repeat, we observe that the effect is executed repeatedly only if both schedules want it to recur. The delay between recurrences is determined by the maximum delay between the two schedules. In this case, the delay follows the progression of the exponential schedule until the maximum number of recurrences specified by the recursive schedule is reached.

Combines two schedules in sequence. First, it follows the policy of the first schedule, then switches to the second schedule once the first completes.

Example (Sequencing Recurs and Spaced Schedules)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<number, unknown, never>
schedule
=
import Schedule
Schedule
.
const andThen: <number, unknown, never, number, unknown, never>(self: Schedule.Schedule<number, unknown, never>, that: Schedule.Schedule<number, unknown, never>) => Schedule.Schedule<number, unknown, never> (+1 overload)

The same as andThenEither, but merges the output.

@since2.0.0

andThen
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(5),
import Schedule
Schedule
.
const spaced: (duration: DurationInput) => Schedule.Schedule<number>

Returns a schedule that recurs continuously, each repetition spaced the specified duration from the last run.

@since2.0.0

spaced
("1 second")
)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, number>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<number, void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<number, unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 0 < recurs
#2 delay: 0
#3 delay: 0
#4 delay: 0
#5 delay: 0
#6 delay: 1000 < spaced
#7 delay: 1000
#8 delay: 1000
#9 delay: 1000
...
*/

When we use the combined schedule with Effect.repeat, we observe that the effect follows the policy of the first schedule (recurs) until it completes the specified number of recurrences. After that, it switches to the policy of the second schedule (spaced) and continues repeating the effect with the fixed delay between recurrences.

A jittered is a combinator that takes one schedule and returns another schedule of the same type except for the delay which is applied randomly

When a resource is out of service due to overload or contention, retrying and backing off doesn’t help us. If all failed API calls are backed off to the same point of time, they cause another overload or contention. Jitter adds some amount of randomness to the delay of the schedule. This helps us to avoid ending up accidentally synchronizing and taking the service down by accident.

Research shows that Schedule.jittered(0.0, 1.0) is very suitable for retrying.

Example (Jittered Exponential Schedule)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<Duration, unknown, never>
schedule
=
import Schedule
Schedule
.
const jittered: <Duration, unknown, never>(self: Schedule.Schedule<Duration, unknown, never>) => Schedule.Schedule<Duration, unknown, never>

Returns a new schedule that randomly modifies the size of the intervals of this schedule.

Defaults min to 0.8 and max to 1.2.

The new interval size is between min * old interval size and max * old interval size.

@since2.0.0

jittered
(
import Schedule
Schedule
.
const exponential: (base: DurationInput, factor?: number) => Schedule.Schedule<Duration>

A schedule that always recurs, but will wait a certain amount between repetitions, given by base * factor.pow(n), where n is the number of repetitions so far. Returns the current duration between recurrences.

@since2.0.0

exponential
("10 millis"))
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, Duration>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<Duration, void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<Duration, unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 9.006765
#2 delay: 20.549507999999996
#3 delay: 45.86659000000001
#4 delay: 77.055037
#5 delay: 178.06722299999998
#6 delay: 376.056965
#7 delay: 728.732785
#8 delay: 1178.174953
#9 delay: 2331.4659370000004
...
*/

In this example, we use the jittered combinator to apply jitter to an exponential schedule. The exponential schedule increases the delay between each repetition exponentially. By adding jitter to the schedule, the delays become randomly adjusted within a certain range.

Schedules can be filtered using Schedule.whileInput or Schedule.whileOutput to control repetition based on input or output conditions.

Example (Filtering Output)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<number, unknown, never>
schedule
=
import Schedule
Schedule
.
const whileOutput: <number, unknown, never>(self: Schedule.Schedule<number, unknown, never>, f: Predicate<number>) => Schedule.Schedule<number, unknown, never> (+1 overload)

Returns a new schedule that continues for as long the specified predicate on the output evaluates to true.

@since2.0.0

whileOutput
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(5), (
n: number
n
) =>
n: number
n
<= 2)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, number>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<number, void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<number, unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 0 < recurs
#2 delay: 0
#3 delay: 0
(end) < whileOutput
*/

In this example, we create a schedule using Schedule.recurs(5) to repeat a certain action up to 5 times. However, we apply the whileOutput combinator with a predicate that filters out outputs greater than 2. As a result, the schedule stops producing outputs once the value exceeds 2, and the repetition ends.

The Schedule.modifyDelay combinator allows you to adjust the delay of a schedule.

Example (Modified Delay Schedule)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<number, unknown, never>
schedule
=
import Schedule
Schedule
.
const modifyDelay: <number, unknown, never>(self: Schedule.Schedule<number, unknown, never>, f: (out: number, duration: Duration) => DurationInput) => Schedule.Schedule<...> (+1 overload)

Returns a new schedule that modifies the delay using the specified function.

@since2.0.0

modifyDelay
(
import Schedule
Schedule
.
const spaced: (duration: DurationInput) => Schedule.Schedule<number>

Returns a schedule that recurs continuously, each repetition spaced the specified duration from the last run.

@since2.0.0

spaced
("1 second"),
(
_: number
_
) => "100 millis"
)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, number>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<number, void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<number, unknown, never>
schedule
)
/*
Output:
delay: 0
#1 delay: 100 < modifyDelay
#2 delay: 100
#3 delay: 100
#4 delay: 100
#5 delay: 100
#6 delay: 100
#7 delay: 100
#8 delay: 100
#9 delay: 100
...
*/

Whenever we need to effectfully process each schedule input/output, we can use Schedule.tapInput and Schedule.tapOutput.

Example (Logging with tapOutput)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Schedule
Schedule
,
import TestClock
TestClock
,
import Fiber
Fiber
,
import TestContext
TestContext
,
import Console
Console
} from "effect"
32 collapsed lines
const
const log: <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>) => void
log
= <
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
,
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
>(
action: Effect.Effect<A, never, never>
action
:
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

The Effect interface defines a value that lazily describes a workflow or job. The workflow requires some context R, and may fail with an error of type E, or succeed with a value of type A.

Effect values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability.

To run an Effect value, you need a Runtime, which is a type that is capable of executing Effect values.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
A
>,
schedule: Schedule.Schedule<Out, void, never>
schedule
:
import Schedule
Schedule
.
interface Schedule<out Out, in In = unknown, out R = never>

A Schedule<Out, In, R> defines a recurring schedule, which consumes values of type In, and which returns values of type Out.

Schedules are defined as a possibly infinite set of intervals spread out over time. Each interval defines a window in which recurrence is possible.

When schedules are used to repeat or retry effects, the starting boundary of each interval produced by a schedule is used as the moment when the effect will be executed again.

Schedules compose in the following primary ways:

  • Union: performs the union of the intervals of two schedules
  • Intersection: performs the intersection of the intervals of two schedules
  • Sequence: concatenates the intervals of one schedule onto another

In addition, schedule inputs and outputs can be transformed, filtered (to terminate a schedule early in response to some input or output), and so forth.

A variety of other operators exist for transforming and combining schedules, and the companion object for Schedule contains all common types of schedules, both for performing retrying, as well as performing repetition.

@since2.0.0

@since2.0.0

Schedule
<
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, void>
): void => {
let
let start: number
start
= 0
let
let i: number
i
= 0
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(function* () {
const
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
:
import Fiber
Fiber
.
interface RuntimeFiber<out A, out E = never>

A runtime fiber that is executing an effect. Runtime fibers have an identity and a trace.

@since2.0.0

RuntimeFiber
<[
function (type parameter) Out in <A, Out>(action: Effect.Effect<A>, schedule: Schedule.Schedule<Out, void>): void
Out
, number]> = yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>> | YieldWrap<Effect.Effect<number, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

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.

@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}`
})

@since2.0.0

gen
(
function* () {
yield*
action: Effect.Effect<A, never, never>
action
const
const now: number
now
= yield*
import TestClock
TestClock
.
const currentTimeMillis: Effect.Effect<number, never, never>

Accesses the current time of a TestClock instance in the context in milliseconds.

@since2.0.0

currentTimeMillis
var console: Console

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

The module exports two specific components:

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

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

Example using the global console:

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

Example using the Console class:

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

@seesource

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

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

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

See util.format() for more information.

@sincev0.1.100

log
(
let i: number
i
=== 0
? `delay: ${
const now: number
now
-
let start: number
start
}`
:
let i: number
i
=== 10
? "..."
: `#${
let i: number
i
} delay: ${
const now: number
now
-
let start: number
start
}`
)
let i: number
i
++
let start: number
start
=
const now: number
now
}
).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[Out, number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[Out, number], never>, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const repeat: <[Out, number], void, never>(schedule: Schedule.Schedule<[Out, number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<[Out, number], E, R> (+3 overloads)

The repeat function returns a new effect that repeats the given effect according to a specified schedule or until the first failure. The scheduled recurrences are in addition to the initial execution, so repeat(action, Schedule.once) executes action once initially, and if it succeeds, repeats it an additional time.

@example

// Success Example
import { Effect, Schedule, Console } from "effect"
const action = Console.log("success")
const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
const program = Effect.repeat(action, policy)
Effect.runPromise(program).then((n) => console.log(`repetitions: ${n}`))

@example

// Failure Example import { Effect, Schedule } from "effect"

let count = 0

// Define an async effect that simulates an action with possible failures const action = Effect.async<string, string>((resume) => { if (count > 1) { console.log("failure") resume(Effect.fail("Uh oh!")) } else { count++ console.log("success") resume(Effect.succeed("yay!")) } })

const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis") const program = Effect.repeat(action, policy)

Effect.runPromiseExit(program).then(console.log)

@since2.0.0

repeat
(
schedule: Schedule.Schedule<Out, void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<Out, void, never>, Schedule.Schedule<[Out, number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<Out, void, never>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
import Schedule
Schedule
.
const intersect: <number, unknown, never>(that: Schedule.Schedule<number, unknown, never>) => <Out, In, R>(self: Schedule.Schedule<Out, In, R>) => Schedule.Schedule<[Out, number], In, R> (+1 overload)

Returns a new schedule that performs a geometric intersection on the intervals defined by both schedules.

@since2.0.0

intersect
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(10)))
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const fork: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>

Returns an effect that forks this effect into its own separate fiber, returning the fiber immediately, without waiting for it to begin executing the effect.

You can use the fork method whenever you want to execute an effect in a new fiber, concurrently and without "blocking" the fiber executing other effects. Using fibers can be tricky, so instead of using this method directly, consider other higher-level methods, such as raceWith, zipPar, and so forth.

The fiber returned by this method has methods to interrupt the fiber and to wait for it to finish executing the effect. See Fiber for more information.

Whenever you use this method to launch a new fiber, the new fiber is attached to the parent fiber's scope. This means when the parent fiber terminates, the child fiber will be terminated as well, ensuring that no fibers leak. This behavior is called "auto supervision", and if this behavior is not desired, you may use the forkDaemon or forkIn methods.

@since2.0.0

fork
)
yield*
import TestClock
TestClock
.
const adjust: (durationInput: DurationInput) => Effect.Effect<void>

Accesses a TestClock instance in the context and increments the time by the specified duration, running any actions scheduled for on or before the new time in order.

@since2.0.0

adjust
(
var Infinity: number
Infinity
)
yield*
import Fiber
Fiber
.
const join: <[Out, number], never>(self: Fiber.Fiber<[Out, number], never>) => Effect.Effect<[Out, number], never, never>

Joins the fiber, which suspends the joining fiber until the result of the fiber has been determined. Attempting to join a fiber that has erred will result in a catchable error. Joining an interrupted fiber will result in an "inner interruption" of this fiber, unlike interruption triggered by another fiber, "inner interruption" can be caught and recovered.

@since2.0.0

join
(
const fiber: Fiber.RuntimeFiber<[Out, number], never>
fiber
)
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>, Promise<void>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>, bc: (_: Effect.Effect<...>) => Promise<...>): Promise<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <TestServices, never, never>(layer: Layer<TestServices, never, never>) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<...> (+9 overloads)

Provides the necessary Layers to an effect, removing its dependency on the environment.

You can pass multiple layers, a Context, Runtime, or ManagedRuntime to the effect.

@seeprovideService for providing a service to an effect.

@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"
// []

@since2.0.0

provide
(
import TestContext
TestContext
.
const TestContext: Layer<TestServices, never, never>

@since2.0.0

TestContext
),
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns the result as a Promise.

When to Use

Use runPromise when you need to execute an effect and work with the result using Promise syntax, typically for compatibility with other promise-based code.

If the effect succeeds, the promise will resolve with the result. If the effect fails, the promise will reject with an error.

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

@example

// Title: Running a Successful Effect as a Promise
import { Effect } from "effect"
Effect.runPromise(Effect.succeed(1)).then(console.log)
// Output: 1

@example

//Example: Handling a Failing Effect as a Rejected Promise import { Effect } from "effect"

Effect.runPromise(Effect.fail("my error")).catch(console.error) // Output: // (FiberFailure) Error: my error

@since2.0.0

runPromise
)
}
const
const schedule: Schedule.Schedule<number, unknown, never>
schedule
=
import Schedule
Schedule
.
const tapOutput: <number, unknown, never, number, void, never>(self: Schedule.Schedule<number, unknown, never>, f: (out: number) => Effect.Effect<void, never, never>) => Schedule.Schedule<number, unknown, never> (+1 overload)

Returns a new schedule that effectfully processes every output from this schedule.

@since2.0.0

tapOutput
(
import Schedule
Schedule
.
const recurs: (n: number) => Schedule.Schedule<number>

A schedule spanning all time, which can be stepped only the specified number of times before it terminates.

@since2.0.0

recurs
(2), (
n: number
n
) =>
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(`repeating ${
n: number
n
}`)
)
const
const action: Effect.Effect<void, never, never>
action
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

@since2.0.0

void
const log: <void, number>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<number, void, never>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<number, unknown, never>
schedule
)
/*
Output:
delay: 0
repeating 0
#1 delay: 0
repeating 1
#2 delay: 0
repeating 2
*/