Skip to content

Cron

The Cron module lets you define schedules in a style similar to UNIX cron expressions. It also supports partial constraints (e.g., certain months or weekdays), time zone awareness through the DateTime module, and robust error handling.

This module helps you:

  • Create a Cron instance from individual parts.
  • Parse and validate cron expressions.
  • Match existing dates to see if they satisfy a given cron schedule.
  • Find the next occurrence of a schedule after a given date.
  • Iterate over future dates that match a schedule.
  • Convert a Cron instance to a Schedule for use in effectful programs.

You can define a cron schedule by specifying numeric constraints for seconds, minutes, hours, days, months, and weekdays. The make function requires you to define all fields representing the schedule’s constraints.

Example (Creating a Cron)

import {
import Cron
Cron
,
import DateTime
DateTime
} from "effect"
// Build a cron that triggers at 4:00 AM
// on the 8th to the 14th of each month
const
const cron: Cron.Cron
cron
=
import Cron
Cron
.
const make: (values: {
readonly seconds?: Iterable<number> | undefined;
readonly minutes: Iterable<number>;
readonly hours: Iterable<number>;
readonly days: Iterable<number>;
readonly months: Iterable<number>;
readonly weekdays: Iterable<number>;
readonly tz?: DateTime.TimeZone | undefined;
}) => Cron.Cron

Creates a Cron instance.

@paramconstraints - The cron constraints.

@since2.0.0

make
({
seconds?: Iterable<number> | undefined
seconds
: [0], // Trigger at the start of a minute
minutes: Iterable<number>
minutes
: [0], // Trigger at the start of an hour
hours: Iterable<number>
hours
: [4], // Trigger at 4:00 AM
days: Iterable<number>
days
: [8, 9, 10, 11, 12, 13, 14], // Specific days of the month
months: Iterable<number>
months
: [], // No restrictions on the month
weekdays: Iterable<number>
weekdays
: [], // No restrictions on the weekday
tz?: DateTime.TimeZone | undefined
tz
:
import DateTime
DateTime
.
const zoneUnsafeMakeNamed: (zoneId: string) => DateTime.TimeZone.Named

Attempt to create a named time zone from a IANA time zone identifier.

If the time zone is invalid, an IllegalArgumentException will be thrown.

@since3.6.0

zoneUnsafeMakeNamed
("Europe/Rome") // Optional time zone
})
  • seconds, minutes, and hours: Define the time of day.
  • days and months: Specify which calendar days and months are valid.
  • weekdays: Restrict the schedule to specific days of the week.
  • tz: Optionally define the time zone for the schedule.

If any field is left empty (e.g., months), it is treated as having “no constraints,” allowing any valid value for that part of the date.

Instead of manually constructing a Cron, you can use UNIX-like cron strings and parse them with parse or unsafeParse.

The parse(cronExpression, tz?) function safely parses a cron string into a Cron instance. It returns an Either, which will contain either the parsed Cron or a parsing error.

Example (Safely Parsing a Cron Expression)

import {
import Either

@since2.0.0

@since2.0.0

Either
,
import Cron
Cron
} from "effect"
// Define a cron expression for 4:00 AM
// on the 8th to the 14th of every month
const
const expression: "0 0 4 8-14 * *"
expression
= "0 0 4 8-14 * *"
// Parse the cron expression
const
const eitherCron: Either.Either<Cron.Cron, Cron.ParseError>
eitherCron
=
import Cron
Cron
.
const parse: (cron: string, tz?: TimeZone | string) => Either.Either<Cron.Cron, Cron.ParseError>

Parses a cron expression into a Cron instance.

@paramcron - The cron expression to parse.

@example

import { Cron, Either } from "effect"
// At 04:00 on every day-of-month from 8 through 14.
assert.deepStrictEqual(Cron.parse("0 0 4 8-14 * *"), Either.right(Cron.make({
seconds: [0],
minutes: [0],
hours: [4],
days: [8, 9, 10, 11, 12, 13, 14],
months: [],
weekdays: []
})))

@since2.0.0

parse
(
const expression: "0 0 4 8-14 * *"
expression
)
if (
import Either

@since2.0.0

@since2.0.0

Either
.
const isRight: <Cron.Cron, Cron.ParseError>(self: Either.Either<Cron.Cron, Cron.ParseError>) => self is Either.Right<Cron.ParseError, Cron.Cron>

Determine if a Either is a Right.

@paramself - The Either to check.

@example

import { Either } from "effect"
assert.deepStrictEqual(Either.isRight(Either.right(1)), true)
assert.deepStrictEqual(Either.isRight(Either.left("a")), false)

@since2.0.0

isRight
(
const eitherCron: Either.Either<Cron.Cron, Cron.ParseError>
eitherCron
)) {
// Successfully parsed
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
("Parsed cron:",
const eitherCron: Either.Right<Cron.ParseError, Cron.Cron>
eitherCron
.
Right<ParseError, Cron>.right: Cron.Cron
right
)
} else {
// Parsing failed
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.error(message?: any, ...optionalParams: any[]): void

Prints to stderr 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 code = 5;
console.error('error #%d', code);
// Prints: error #5, to stderr
console.error('error', code);
// Prints: error 5, to stderr

If formatting elements (e.g. %d) are not found in the first string then util.inspect() is called on each argument and the resulting string values are concatenated. See util.format() for more information.

@sincev0.1.100

error
("Failed to parse cron:",
const eitherCron: Either.Left<Cron.ParseError, Cron.Cron>
eitherCron
.
Left<ParseError, Cron>.left: Cron.ParseError
left
.
ParseError.message: string
message
)
}

The unsafeParse(cronExpression, tz?) function works like parse, but instead of returning an Either, it throws an exception if the input is invalid.

Example (Parsing a Cron Expression)

import {
import Cron
Cron
} from "effect"
// Parse a cron expression for 4:00 AM
// on the 8th to the 14th of every month
// Throws if the expression is invalid
const
const cron: Cron.Cron
cron
=
import Cron
Cron
.
const unsafeParse: (cron: string, tz?: TimeZone | string) => Cron.Cron

Parses a cron expression into a Cron instance.

Throws on failure.

@paramcron - The cron expression to parse.

@example

import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14.
assert.deepStrictEqual(Cron.unsafeParse("0 4 8-14 * *"), Cron.make({
minutes: [0],
hours: [4],
days: [8, 9, 10, 11, 12, 13, 14],
months: [],
weekdays: []
}))

@since2.0.0

unsafeParse
("0 0 4 8-14 * *")

The match function allows you to determine if a given Date (or any DateTime.Input) satisfies the constraints of a cron schedule.

If the date meets the schedule’s conditions, match returns true. Otherwise, it returns false.

Example (Checking if a Date Matches a Cron Schedule)

import {
import Cron
Cron
} from "effect"
// Suppose we have a cron that triggers at 4:00 AM
// on the 8th to the 14th of each month
const
const cron: Cron.Cron
cron
=
import Cron
Cron
.
const unsafeParse: (cron: string, tz?: TimeZone | string) => Cron.Cron

Parses a cron expression into a Cron instance.

Throws on failure.

@paramcron - The cron expression to parse.

@example

import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14.
assert.deepStrictEqual(Cron.unsafeParse("0 4 8-14 * *"), Cron.make({
minutes: [0],
hours: [4],
days: [8, 9, 10, 11, 12, 13, 14],
months: [],
weekdays: []
}))

@since2.0.0

unsafeParse
("0 0 4 8-14 * *")
const
const checkDate: Date
checkDate
= new
var Date: DateConstructor
new (value: number | string | Date) => Date (+3 overloads)
Date
("2025-01-08 04:00:00")
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
(
import Cron
Cron
.
const match: (cron: Cron.Cron, date: DateTime.Input) => boolean

Checks if a given Date falls within an active Cron time window.

@throwsIllegalArgumentException if the given DateTime.Input is invalid.

@paramcron - The Cron instance.

@paramdate - The Date to check against.

@example

import { Cron, Either } from "effect"
const cron = Either.getOrThrow(Cron.parse("0 4 8-14 * *"))
assert.deepStrictEqual(Cron.match(cron, new Date("2021-01-08 04:00:00")), true)
assert.deepStrictEqual(Cron.match(cron, new Date("2021-01-08 05:00:00")), false)

@since2.0.0

match
(
const cron: Cron.Cron
cron
,
const checkDate: Date
checkDate
))
// Output: true

The next function determines the next date that satisfies a given cron schedule, starting from a specified date. If no starting date is provided, the current time is used as the starting point.

If next cannot find a matching date within a predefined number of iterations, it throws an error to prevent infinite loops.

Example (Determining the Next Matching Date)

import {
import Cron
Cron
} from "effect"
// Define a cron expression for 4:00 AM
// on the 8th to the 14th of every month
const
const cron: Cron.Cron
cron
=
import Cron
Cron
.
const unsafeParse: (cron: string, tz?: TimeZone | string) => Cron.Cron

Parses a cron expression into a Cron instance.

Throws on failure.

@paramcron - The cron expression to parse.

@example

import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14.
assert.deepStrictEqual(Cron.unsafeParse("0 4 8-14 * *"), Cron.make({
minutes: [0],
hours: [4],
days: [8, 9, 10, 11, 12, 13, 14],
months: [],
weekdays: []
}))

@since2.0.0

unsafeParse
("0 0 4 8-14 * *", "UTC")
// Specify the starting point for the search
const
const after: Date
after
= new
var Date: DateConstructor
new (value: number | string | Date) => Date (+3 overloads)
Date
("2025-01-08")
// Find the next matching date
const
const nextDate: Date
nextDate
=
import Cron
Cron
.
const next: (cron: Cron.Cron, now?: DateTime.Input) => Date

Returns the next run Date for the given Cron instance.

Uses the current time as a starting point if no value is provided for now.

@throwsIllegalArgumentException if the given DateTime.Input is invalid.

@throwsError if the next run date cannot be found within 10,000 iterations.

@example

import { Cron, Either } from "effect"
const after = new Date("2021-01-01 00:00:00")
const cron = Either.getOrThrow(Cron.parse("0 4 8-14 * *"))
assert.deepStrictEqual(Cron.next(cron, after), new Date("2021-01-08 04:00:00"))

@paramcron - The Cron instance.

@paramnow - The Date to start searching from.

@since2.0.0

next
(
const cron: Cron.Cron
cron
,
const after: Date
after
)
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
(
const nextDate: Date
nextDate
)
// Output: 2025-01-08T04:00:00.000Z

To generate multiple future dates that match a cron schedule, you can use the sequence function. This function provides an infinite iterator of matching dates, starting from a specified date.

Example (Generating Future Dates with an Iterator)

import { Cron } from "effect"
// Define a cron expression for 4:00 AM
// on the 8th to the 14th of every month
const cron = Cron.unsafeParse("0 0 4 8-14 * *", "UTC")
// Specify the starting date
const start = new Date("2021-01-08")
// Create an iterator for the schedule
const iterator = Cron.sequence(cron, start)
// Get the first matching date after the start date
console.log(iterator.next().value)
// Output: 2021-01-08T04:00:00.000Z
// Get the second matching date after the start date
console.log(iterator.next().value)
// Output: 2021-01-09T04:00:00.000Z

The Schedule module allows you to define recurring behaviors, such as retries or periodic events. The cron function bridges the Cron module with the Schedule module, enabling you to create schedules based on cron expressions or Cron instances.

The Schedule.cron function generates a Schedule that triggers at the start of each interval defined by the provided cron expression or Cron instance. When triggered, the schedule produces a tuple [start, end] representing the timestamps (in milliseconds) of the cron interval window.

Example (Creating a Schedule from a Cron)

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 Cron
Cron
,
import Console
Console
} from "effect"
// A helper function to log output at each interval of the schedule
29 collapsed lines
const
const log: <A>(action: Effect.Effect<A>, schedule: Schedule.Schedule<[number, number], void>) => void
log
= <
function (type parameter) A in <A>(action: Effect.Effect<A>, schedule: Schedule.Schedule<[number, number], void>): void
A
>(
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 describes a workflow or job, which can succeed or fail.

Details

The Effect interface represents a computation that can model a workflow involving various types of operations, such as synchronous, asynchronous, concurrent, and parallel interactions. It operates within a context of type R, and the result can either be a success with a value of type A or a failure with an error of type E. The Effect is designed to handle complex interactions with external resources, offering advanced features such as fiber-based concurrency, scheduling, interruption handling, and scalability. This makes it suitable for tasks that require fine-grained control over concurrency and error management.

To execute an Effect value, you need a Runtime, which provides the environment necessary to run and manage the computation.

@since2.0.0

@since2.0.0

Effect
<
function (type parameter) A in <A>(action: Effect.Effect<A>, schedule: Schedule.Schedule<[number, number], void>): void
A
>,
schedule: Schedule.Schedule<[number, number], 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
<[number, number], void>
): void => {
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

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

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

@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<[[number, number], 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
<[[number, number], number]> =
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<A, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<A, 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

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

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

@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
let i: number
i
++
}).
Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<[[number, number], number], never, never>, Effect.Effect<Fiber.RuntimeFiber<[[number, number], 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: <[[number, number], number], void, never>(schedule: Schedule.Schedule<[[number, number], number], void, never>) => <E, R>(self: Effect.Effect<void, E, R>) => Effect.Effect<...> (+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<[number, number], void, never>
schedule
.
Pipeable.pipe<Schedule.Schedule<[number, number], void, never>, Schedule.Schedule<[[number, number], number], void, never>, Schedule.Schedule<[[number, number], number], void, never>>(this: Schedule.Schedule<...>, ab: (_: Schedule.Schedule<...>) => Schedule.Schedule<...>, bc: (_: Schedule.Schedule<...>) => Schedule.Schedule<...>): Schedule.Schedule<...> (+21 overloads)
pipe
(
// Limit the number of iterations for the example
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 Schedule
Schedule
.
const tapOutput: <[[number, number], number], void, never, [[number, number], number]>(f: (out: [[number, number], number]) => Effect.Effect<void, never, never>) => <In, R>(self: Schedule.Schedule<[[...], number], In, R>) => Schedule.Schedule<...> (+1 overload)

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

@since2.0.0

tapOutput
(([
type Out: [number, number]
Out
]) =>
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(
let i: number
i
=== 11 ? "..." : [new
var Date: DateConstructor
new (value: number | string | Date) => Date (+3 overloads)
Date
(
type Out: [number, number]
Out
[0]), new
var Date: DateConstructor
new (value: number | string | Date) => Date (+3 overloads)
Date
(
type Out: [number, number]
Out
[1])]
)
)
)
),
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: <[[number, number], number], never>(self: Fiber.Fiber<[[number, number], number], never>) => Effect.Effect<[[number, number], 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<[[number, number], 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
)
}
// Build a cron that triggers at 4:00 AM
// on the 8th to the 14th of each month
const
const cron: Cron.Cron
cron
=
import Cron
Cron
.
const unsafeParse: (cron: string, tz?: TimeZone | string) => Cron.Cron

Parses a cron expression into a Cron instance.

Throws on failure.

@paramcron - The cron expression to parse.

@example

import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14.
assert.deepStrictEqual(Cron.unsafeParse("0 4 8-14 * *"), Cron.make({
minutes: [0],
hours: [4],
days: [8, 9, 10, 11, 12, 13, 14],
months: [],
weekdays: []
}))

@since2.0.0

unsafeParse
("0 0 4 8-14 * *", "UTC")
// Convert the Cron into a Schedule
const
const schedule: Schedule.Schedule<[number, number], unknown, never>
schedule
=
import Schedule
Schedule
.
const cron: (cron: Cron.Cron) => Schedule.Schedule<[number, number]> (+1 overload)

Cron schedule that recurs every interval that matches the schedule.

It triggers at the beginning of each cron interval, producing the timestamps of the cron window.

NOTE: expression parameter is validated lazily. Must be a valid cron expression.

@since2.0.0

cron
(
const cron: Cron.Cron
cron
)
// Define a dummy action to repeat
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

Represents an effect that does nothing and produces no value.

When to Use

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

@since2.0.0

void
// Log the schedule intervals
const log: <void>(action: Effect.Effect<void, never, never>, schedule: Schedule.Schedule<[number, number], void>) => void
log
(
const action: Effect.Effect<void, never, never>
action
,
const schedule: Schedule.Schedule<[number, number], unknown, never>
schedule
)
/*
Output:
[ 1970-01-08T04:00:00.000Z, 1970-01-08T04:00:01.000Z ]
[ 1970-01-09T04:00:00.000Z, 1970-01-09T04:00:01.000Z ]
[ 1970-01-10T04:00:00.000Z, 1970-01-10T04:00:01.000Z ]
[ 1970-01-11T04:00:00.000Z, 1970-01-11T04:00:01.000Z ]
[ 1970-01-12T04:00:00.000Z, 1970-01-12T04:00:01.000Z ]
[ 1970-01-13T04:00:00.000Z, 1970-01-13T04:00:01.000Z ]
[ 1970-01-14T04:00:00.000Z, 1970-01-14T04:00:01.000Z ]
[ 1970-02-08T04:00:00.000Z, 1970-02-08T04:00:01.000Z ]
[ 1970-02-09T04:00:00.000Z, 1970-02-09T04:00:01.000Z ]
[ 1970-02-10T04:00:00.000Z, 1970-02-10T04:00:01.000Z ]
...
*/