Ticks on a cron schedule — each wait sleeps until the expression's NEXT occurrence (UTC),
so ticks land on calendar boundaries instead of relative intervals. requestWake /
resetCadence end the current wait early (the tick runs now; the next wait re-aims at the
following occurrence). An invalid expression fails AT CONSTRUCTION, not at the first tick.
For arming/disarming by calendar windows use a schedule (ProcessSchedule); cron is
cadence WITHIN the armed window.
export const const cron: (
expression: string | Cron.Cron
) => Layer.Layer<PollingTag>
Ticks on a cron schedule — each wait sleeps until the expression's NEXT occurrence (UTC),
so ticks land on calendar boundaries instead of relative intervals. requestWake /
resetCadence end the current wait early (the tick runs now; the next wait re-aims at the
following occurrence). An invalid expression fails AT CONSTRUCTION, not at the first tick.
For arming/disarming by calendar windows use a schedule (
ProcessSchedule
); cron is
cadence WITHIN the armed window.
cron = (
expression: string | Cron.Cronexpression: string | import CronCron.Cron
): import LayerLayer.interface Layer<in ROut, out E = never, out RIn = never>A Layer describes how to build one or more services for dependency injection.
When to use
Use to model construction of application services for dependency injection,
especially when services have dependencies, can fail during construction, or
need scoped setup and release.
Details
A Layer<ROut, E, RIn> represents ROut as the services this layer
provides, E as the possible errors during layer construction, and RIn as
the services this layer requires as dependencies.
Layer<import PollingTagPollingTag> => {
// eager + loud: a bad expression is a construction defect, never a silent never-ticking poll
const const parsed: Cron.Cronconst parsed: {
tz: Option.Option<DateTime.TimeZone>;
seconds: ReadonlySet<number>;
minutes: ReadonlySet<number>;
hours: ReadonlySet<number>;
days: ReadonlySet<number>;
months: ReadonlySet<number>;
weekdays: ReadonlySet<number>;
and: boolean;
first: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
last: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
next: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
prev: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
parsed =
typeof expression: string | Cron.Cronexpression === "string" ? import CronCron.const parseUnsafe: (
cron: string,
tz?: DateTime.TimeZone | string
) => Cron.Cron
Parses a cron expression into a Cron instance, throwing on failure.
When to use
Use when you expect the input to be valid and want to avoid handling the
Result type.
Example (Parsing cron expressions unsafely)
import { Cron } from "effect"
// At 04:00 on every day-of-month from 8 through 14
const cron = Cron.parseUnsafe("0 0 4 8-14 * *")
// With timezone
const cronWithTz = Cron.parseUnsafe("0 0 9 * * *", "America/New_York")
// This would throw an error
// const invalid = Cron.parseUnsafe("invalid expression")
parseUnsafe(expression: stringexpression) : expression: Cron.Cron(parameter) expression: {
tz: Option.Option<DateTime.TimeZone>;
seconds: ReadonlySet<number>;
minutes: ReadonlySet<number>;
hours: ReadonlySet<number>;
days: ReadonlySet<number>;
months: ReadonlySet<number>;
weekdays: ReadonlySet<number>;
and: boolean;
first: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
last: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
next: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
prev: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
expression;
return import registerPollingLayerregisterPollingLayer(
import LayerLayer.const effect: <unknown, unknown, never, never>(service: Key<unknown, unknown>, effect: Effect.Effect<unknown, never, never>) => Layer.Layer<unknown, never, never> (+1 overload)Constructs a layer from an effect that produces a single service.
When to use
Use when you need to construct a Layer-provided service with an Effect,
dependencies, or scoped resource acquisition.
Details
This allows you to create a Layer from an Effect that produces a service.
The Effect is executed in the scope of the layer, allowing for proper
resource management.
Example (Creating a layer from an effect)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
const layer = Layer.effect(Database,
Effect.sync(() => ({
query: (sql: string) => Effect.succeed(`Query: ${sql}`)
}))
)
effect(
import PollingTagPollingTag,
import EffectEffect.const gen: <Effect.Effect<Ref.Ref<Deferred.Deferred<void, never>>, never, never>, PollingService>(f: () => Generator<Effect.Effect<Ref.Ref<Deferred.Deferred<void, never>>, never, never>, PollingService, never>) => Effect.Effect<PollingService, never, never> (+1 overload)Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: 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}`
})
gen(function* () {
const const wakeRef: Ref.Ref<
Deferred.Deferred<void, never>
>
const wakeRef: {
ref: MutableRef.MutableRef<A>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
wakeRef = yield* import RefRef.const make: <Deferred.Deferred<void, never>>(value: Deferred.Deferred<void, never>) => Effect.Effect<Ref.Ref<Deferred.Deferred<void, never>>, never, never>Creates a new Ref with the specified initial value.
When to use
Use to create a Ref for shared mutable state inside an Effect program.
Example (Creating a ref)
import { Effect, Ref } from "effect"
const program = Effect.gen(function*() {
const ref = yield* Ref.make(42)
const value = yield* Ref.get(ref)
console.log(value) // 42
})
make<import DeferredDeferred.interface Deferred<in out A, in out E = never>A Deferred represents an asynchronous variable that can be set exactly
once, with the ability for an arbitrary number of fibers to suspend (by
calling Deferred.await) and automatically resume when the variable is set.
When to use
Use to coordinate multiple fibers around a value or failure that will be
supplied exactly once.
Example (Creating a Deferred for inter-fiber communication)
import { Deferred, Effect, Fiber } from "effect"
// Create and use a Deferred for inter-fiber communication
const program = Effect.gen(function*() {
// Create a Deferred that will hold a string value
const deferred: Deferred.Deferred<string> = yield* Deferred.make<string>()
// Fork a fiber that will set the deferred value
const producer = yield* Effect.forkChild(
Effect.gen(function*() {
yield* Effect.sleep("100 millis")
yield* Deferred.succeed(deferred, "Hello, World!")
})
)
// Fork a fiber that will await the deferred value
const consumer = yield* Effect.forkChild(
Effect.gen(function*() {
const value = yield* Deferred.await(deferred)
console.log("Received:", value)
return value
})
)
// Wait for both fibers to complete
yield* Fiber.join(producer)
const result = yield* Fiber.join(consumer)
return result
})
Companion namespace containing type-level metadata for Deferred.
When to use
Use to reference type-level metadata associated with Deferred.
Deferred<void, never>>(
import DeferredDeferred.const makeUnsafe: <void, never>() => Deferred.Deferred<void, never>Creates an empty Deferred synchronously outside the Effect runtime.
When to use
Use to allocate a Deferred synchronously when direct allocation outside
Effect is required.
Example (Creating a Deferred unsafely)
import { Deferred } from "effect"
const deferred = Deferred.makeUnsafe<number>()
console.log(deferred)
makeUnsafe()
);
const const requestWake: Effect.Effect<
void,
never,
never
>
const requestWake: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
requestWake = import EffectEffect.const flatMap: <Deferred.Deferred<void, never>, never, never, boolean, never, never>(self: Effect.Effect<Deferred.Deferred<void, never>, never, never>, f: (a: Deferred.Deferred<void, never>) => Effect.Effect<boolean, never, never>) => Effect.Effect<boolean, never, never> (+1 overload)Chains effects to produce new Effect instances, useful for combining
operations that depend on previous results.
When to use
Use when you need to chain multiple effects, ensuring that each
step produces a new Effect while flattening any nested effects that may
occur.
Details
flatMap lets you sequence effects so that the result of one effect can be
used in the next step. It is similar to flatMap used with arrays but works
specifically with Effect instances, allowing you to avoid deeply nested
effect structures.
Since effects are immutable, flatMap always returns a new effect instead of
changing the original one.
Example (Choosing flatMap syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => Effect.succeed(n + 1)
const flatMappedWithPipe = pipe(myEffect, Effect.flatMap(transformation))
const flatMappedWithDataFirst = Effect.flatMap(myEffect, transformation)
const flatMappedWithMethod = myEffect.pipe(Effect.flatMap(transformation))
Example (Sequencing dependent effects)
import { Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Chaining the fetch and discount application using `flatMap`
const finalAmount = pipe(
fetchTransactionAmount,
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 95
flatMap(import RefRef.const get: <Deferred.Deferred<void, never>>(self: Ref.Ref<Deferred.Deferred<void, never>>) => Effect.Effect<Deferred.Deferred<void, never>, never, never>Gets the current value of the Ref.
When to use
Use to read the current Ref value without changing it.
Example (Getting the current value)
import { Effect, Ref } from "effect"
const program = Effect.gen(function*() {
const ref = yield* Ref.make(42)
const value = yield* Ref.get(ref)
console.log(value) // 42
})
get(const wakeRef: Ref.Ref<
Deferred.Deferred<void, never>
>
const wakeRef: {
ref: MutableRef.MutableRef<A>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
wakeRef), (d: Deferred.Deferred<void, never>(parameter) d: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
d) =>
import DeferredDeferred.const succeed: <void | undefined, never>(self: Deferred.Deferred<void | undefined, never>, value: void | undefined) => Effect.Effect<boolean> (+1 overload)Attempts to complete the Deferred with the specified value.
When to use
Use to complete a Deferred with a successful value.
Details
Fibers waiting on the Deferred receive the value only if this call
completes it. The returned effect succeeds with true when this call
completed the Deferred, or false if it was already completed.
Example (Completing a Deferred with a value)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() {
const deferred = yield* Deferred.make<number>()
yield* Deferred.succeed(deferred, 42)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})
succeed(d: Deferred.Deferred<void, never>(parameter) d: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
d, var undefinedundefined)
).Pipeable.pipe<Effect.Effect<boolean, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<boolean, never, never>, ab: (_: Effect.Effect<boolean, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+21 overloads)pipe(import EffectEffect.const asVoid: <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<void, E, R>
Maps the success value of an Effect to void, preserving failures.
Example (Discarding success values)
import { Effect } from "effect"
const program = Effect.asVoid(Effect.succeed(42))
Effect.runPromise(program).then(console.log)
// undefined (void)
asVoid);
const const untilNext: Effect.Effect<
Duration.Duration,
never,
never
>
const untilNext: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
untilNext = import EffectEffect.const map: <number, never, never, Duration.Duration>(self: Effect.Effect<number, never, never>, f: (a: number) => Duration.Duration) => Effect.Effect<Duration.Duration, never, never> (+1 overload)Transforms the value inside an effect by applying a function to it.
When to use
Use to transform an effect's success value with a function that returns a
plain value, producing a new effect without changing the original effect's
typed error or context requirements.
Details
map takes a function and applies it to the value contained within an
effect, creating a new effect with the transformed value.
It's important to note that effects are immutable, meaning that the original
effect is not modified. Instead, a new effect is returned with the updated
value.
Example (Choosing map syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => n + 1
const mappedWithPipe = pipe(myEffect, Effect.map(transformation))
const mappedWithDataFirst = Effect.map(myEffect, transformation)
const mappedWithMethod = myEffect.pipe(Effect.map(transformation))
Example (Adding a service charge)
import { Effect, pipe } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
Effect.map(addServiceCharge)
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
map(import ClockClock.const currentTimeMillis: Effect.Effect<
number,
never,
never
>
const currentTimeMillis: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Returns an Effect that succeeds with the current time in milliseconds.
When to use
Use to read wall-clock time from the active Clock service with millisecond
precision.
Example (Reading milliseconds)
import { Clock, Effect } from "effect"
const program = Effect.gen(function*() {
const currentTime = yield* Clock.currentTimeMillis
console.log(`Current time: ${currentTime}ms`)
return currentTime
})
currentTimeMillis, (now: numbernow) =>
import DurationDuration.const millis: (
millis: number
) => Duration.Duration
Creates a Duration from milliseconds.
Example (Creating durations from milliseconds)
import { Duration } from "effect"
const duration = Duration.millis(1000)
console.log(Duration.toMillis(duration)) // 1000
millis(
var Math: MathAn intrinsic object that provides basic mathematics functionality and constants.
Math.Math.max(...values: number[]): numberReturns the larger of a set of supplied numeric expressions.
max(
0,
import CronCron.const next: (
cron: Cron.Cron,
now?: DateTime.DateTime.Input
) => Date
Returns the next scheduled date/time for the given Cron instance.
When to use
Use to find the next occurrence of a cron schedule after a specific date/time
or after the current time.
Details
Searches for the next date and time when the cron schedule should trigger,
starting after the specified date/time or after the current time when no
date is provided.
Example (Finding the next occurrence)
import { Cron, Result } from "effect"
const cron = Result.getOrThrow(Cron.parse("0 0 4 8-14 * *"))
// Get next run after a specific date
const after = new Date("2021-01-01T00:00:00Z")
const nextRun = Cron.next(cron, after)
console.log(nextRun) // 2021-01-08T04:00:00.000Z
// Get next run from current time
const nextFromNow = Cron.next(cron)
console.log(nextFromNow) // Next occurrence from now
next(
const parsed: Cron.Cronconst parsed: {
tz: Option.Option<DateTime.TimeZone>;
seconds: ReadonlySet<number>;
minutes: ReadonlySet<number>;
hours: ReadonlySet<number>;
days: ReadonlySet<number>;
months: ReadonlySet<number>;
weekdays: ReadonlySet<number>;
and: boolean;
first: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
last: { readonly second: number; readonly minute: number; readonly hour: number; readonly day: number; readonly month: number; readonly weekday: number };
next: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
prev: { readonly second: ReadonlyArray<number | undefined>; readonly minute: ReadonlyArray<number | undefined>; readonly hour: ReadonlyArray<number | undefined>; readonly day: ReadonlyArray<number | undefined>; readonly month: ReadonlyArray<numb…;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
parsed,
import DateTimeDateTime.const toDateUtc: (
self: DateTime.DateTime
) => Date
Gets the UTC Date of a DateTime.
Details
This always returns the UTC representation, ignoring any time zone information.
Example (Converting DateTime values to UTC Dates)
import { DateTime } from "effect"
const dt = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
timeZone: "Europe/London"
})
const utcDate = DateTime.toDateUtc(dt)
console.log(utcDate.toISOString()) // "2024-01-01T12:00:00.000Z"
toDateUtc(import DateTimeDateTime.const makeUnsafe: <number>(
input: number
) => DateTime.Utc
Create a DateTime from supported input values.
When to use
Use when creating a DateTime from trusted input and construction failures
should throw an IllegalArgumentError instead of returning Option.none.
Details
- A
DateTime
- A
Date instance (invalid dates will throw an IllegalArgumentError)
- The
number of milliseconds since the Unix epoch
- An object with the parts of a date
- A
string that can be parsed by Date.parse
Example (Creating DateTime values unsafely)
import { DateTime } from "effect"
// from Date
const fromDate = DateTime.makeUnsafe(new Date("2024-01-01T12:00:00Z"))
console.log(DateTime.formatIso(fromDate)) // "2024-01-01T12:00:00.000Z"
// from parts
const fromParts = DateTime.makeUnsafe({ year: 2024 })
console.log(DateTime.formatIso(fromParts)) // "2024-01-01T00:00:00.000Z"
// from string
const fromString = DateTime.makeUnsafe("2024-01-01")
console.log(DateTime.formatIso(fromString)) // "2024-01-01T00:00:00.000Z"
makeUnsafe(now: numbernow))
).Date.getTime(): numberReturns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
getTime() - now: numbernow
)
)
);
const const awaitNextTick: Effect.Effect<
void,
never,
never
>
const awaitNextTick: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
awaitNextTick = import EffectEffect.const gen: <Effect.Effect<void, never, never>, void>(f: () => Generator<Effect.Effect<void, never, never>, void, never>) => Effect.Effect<void, never, never> (+1 overload)Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: 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}`
})
gen(function* () {
const const d: Deferred.Deferred<void, never>const d: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
d = import DeferredDeferred.const makeUnsafe: <void, never>() => Deferred.Deferred<void, never>Creates an empty Deferred synchronously outside the Effect runtime.
When to use
Use to allocate a Deferred synchronously when direct allocation outside
Effect is required.
Example (Creating a Deferred unsafely)
import { Deferred } from "effect"
const deferred = Deferred.makeUnsafe<number>()
console.log(deferred)
makeUnsafe<void, never>();
yield* import RefRef.const set: <Deferred.Deferred<void, never>>(self: Ref.Ref<Deferred.Deferred<void, never>>, value: Deferred.Deferred<void, never>) => Effect.Effect<void> (+1 overload)set(const wakeRef: Ref.Ref<
Deferred.Deferred<void, never>
>
const wakeRef: {
ref: MutableRef.MutableRef<A>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
wakeRef, const d: Deferred.Deferred<void, never>const d: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
d);
const const dur: Duration.Durationconst dur: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
dur = yield* const untilNext: Effect.Effect<
Duration.Duration,
never,
never
>
const untilNext: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
untilNext;
yield* import EffectEffect.const race: <void, never, never, void, never, never>(self: Effect.Effect<void, never, never>, that: Effect.Effect<void, never, never>, options?: {
readonly onWinner?: (options: {
readonly fiber: Fiber<any, any>;
readonly index: number;
readonly parentFiber: Fiber<any, any>;
}) => void;
}) => Effect.Effect<void, never, never> (+1 overload)
Races two effects and returns the first successful result.
Details
If one effect succeeds, the other is interrupted and onWinner can observe the
winning fiber. If both fail, the race fails.
Example (Racing two effects)
import { Console, Duration, Effect } from "effect"
const fastFail = Effect.delay(Effect.fail("fast-fail"), Duration.millis(10))
const slowSuccess = Effect.delay(Effect.succeed("slow-success"), Duration.millis(50))
const program = Effect.gen(function*() {
const result = yield* Effect.race(fastFail, slowSuccess)
yield* Console.log(`winner: ${result}`)
})
Effect.runPromise(program)
// Output: winner: slow-success
race(import EffectEffect.const sleep: (
duration: Duration.Input
) => Effect.Effect<void>
Returns an effect that suspends the current fiber for the specified duration
without blocking a JavaScript thread.
Example (Pausing without blocking)
import { Console, Effect } from "effect"
const program = Effect.gen(function*() {
yield* Console.log("Start")
yield* Effect.sleep("2 seconds")
yield* Console.log("End")
})
Effect.runFork(program)
// Output: "Start" (immediately)
// Output: "End" (after 2 seconds)
sleep(const dur: Duration.Durationconst dur: {
value: DurationValue;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
dur), import DeferredDeferred.await<void, never>(self: Deferred.Deferred<void, never>): Effect.Effect<void, never, never>
export await
Retrieves the value of the Deferred, suspending the fiber running the
workflow until the result is available.
When to use
Use to wait for a Deferred to be completed and resume with its success,
failure, defect, or interruption.
Details
Awaiters observe the completion effect stored in the Deferred.
Example (Awaiting a Deferred value)
import { Deferred, Effect } from "effect"
const program = Effect.gen(function*() {
const deferred = yield* Deferred.make<number>()
yield* Deferred.succeed(deferred, 42)
const value = yield* Deferred.await(deferred)
console.log(value) // 42
})
await(const d: Deferred.Deferred<void, never>const d: {
effect: Effect<A, E>;
resumes: Array<(effect: Effect<A, E>) => void> | undefined;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
d)).Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+21 overloads)pipe(
import EffectEffect.const asVoid: <A, E, R>(
self: Effect.Effect<A, E, R>
) => Effect.Effect<void, E, R>
Maps the success value of an Effect to void, preserving failures.
Example (Discarding success values)
import { Effect } from "effect"
const program = Effect.asVoid(Effect.succeed(42))
Effect.runPromise(program).then(console.log)
// undefined (void)
asVoid
);
});
return {
awaitNextTick: Effect.Effect<void, never, never>(property) awaitNextTick: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
awaitNextTick,
requestWake: Effect.Effect<void, never, never>(property) requestWake: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
requestWake,
resetCadence: Effect.Effect<void, never, never>(property) resetCadence: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
resetCadence: const requestWake: Effect.Effect<
void,
never,
never
>
const requestWake: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
requestWake,
afterTick: Effect.Effect<void, never, never>(property) afterTick: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
afterTick: import EffectEffect.const void: Effect.Effect<void, never, never>
export void
(alias) const void: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
Returns an effect that succeeds with void.
void,
peekCadence: Effect.Effect<
Option.Option<Duration.Duration>,
never,
never
>
(property) peekCadence: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
peekCadence: import EffectEffect.const map: <Duration.Duration, never, never, Option.Option<Duration.Duration>>(self: Effect.Effect<Duration.Duration, never, never>, f: (a: Duration.Duration) => Option.Option<Duration.Duration>) => Effect.Effect<Option.Option<Duration.Duration>, never, never> (+1 overload)Transforms the value inside an effect by applying a function to it.
When to use
Use to transform an effect's success value with a function that returns a
plain value, producing a new effect without changing the original effect's
typed error or context requirements.
Details
map takes a function and applies it to the value contained within an
effect, creating a new effect with the transformed value.
It's important to note that effects are immutable, meaning that the original
effect is not modified. Instead, a new effect is returned with the updated
value.
Example (Choosing map syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => n + 1
const mappedWithPipe = pipe(myEffect, Effect.map(transformation))
const mappedWithDataFirst = Effect.map(myEffect, transformation)
const mappedWithMethod = myEffect.pipe(Effect.map(transformation))
Example (Adding a service charge)
import { Effect, pipe } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
Effect.map(addServiceCharge)
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
map(const untilNext: Effect.Effect<
Duration.Duration,
never,
never
>
const untilNext: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
untilNext, import OptionOption.const some: <A>(
value: A
) => Option.Option<A>
Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some),
} satisfies import PollingServicePollingService;
})
)
);
};