Skip to content

Layer Memoization

Layer memoization allows a layer to be created once and used multiple times in the dependency graph. If we use the same layer twice:

Layer.merge(Layer.provide(L2, L1), Layer.provide(L3, L1))

then the L1 layer will be allocated only once.

One important feature of an Effect application is that layers are shared by default. This means that if the same layer is used twice, and if we provide the layer globally, the layer will only be allocated a single time. For every layer in our dependency graph, there is only one instance of it that is shared between all the layers that depend on it.

Example

For example, assume we have the three services A, B, and C. The implementation of both B and C is dependent on the A service:

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Context

@since2.0.0

@since2.0.0

Context
,
import Layer
Layer
} from "effect"
class
class A
A
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("A")<
class A
A
, { readonly
a: number
a
: number }>() {}
class
class B
B
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"B">(id: "B") => <Self, Shape>() => Context.TagClass<Self, "B", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("B")<
class B
B
, { readonly
b: string
b
: string }>() {}
class
class C
C
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"C">(id: "C") => <Self, Shape>() => Context.TagClass<Self, "C", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("C")<
class C
C
, { readonly
c: boolean
c
: boolean }>() {}
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{
readonly a: number;
}, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class A
A
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <{
a: number;
}>(value: {
a: number;
}) => Effect.Effect<{
a: number;
}, never, never>

Creates an Effect that succeeds with the provided value.

Use this function to represent a successful computation that yields a value of type A. The effect does not fail and does not require any environmental context.

@example

import { Effect } from "effect"

// Creating an effect that succeeds with the number 42 const success = Effect.succeed(42)

@since2.0.0

succeed
({
a: number
a
: 5 }).
Pipeable.pipe<Effect.Effect<{
a: number;
}, never, never>, Effect.Effect<{
a: number;
}, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{
a: number;
}, never, never>) => Effect.Effect<{
a: number;
}, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tap: <{
a: number;
}, Effect.Effect<void, never, never>>(f: (a: {
a: number;
}) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{
a: number;
}, E, R>) => Effect.Effect<...> (+7 overloads)

@since2.0.0

tap
(() =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using Cause instances.

To adjust the log level, use the Logger.withMinimumLogLevel function.

@example

import { Cause, Effect } from "effect"

const program = Effect.log( "message1", "message2", Cause.die("Oh no!"), Cause.die("Oh uh!") )

// Effect.runFork(program) // Output: // timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no! // Error: Oh uh!"

@since2.0.0

log
("initialized"))
)
)
const
const BLive: Layer.Layer<B, never, A>
BLive
=
import Layer
Layer
.
const effect: <typeof B, never, A>(tag: typeof B, effect: Effect.Effect<{
readonly b: string;
}, never, A>) => Layer.Layer<B, never, A> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class B
B
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
b: string;
}>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
b: string;
}, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
const {
const a: number
a
} = yield*
class A
A
return {
b: string
b
:
var String: StringConstructor
(value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(
const a: number
a
) }
})
)
const
const CLive: Layer.Layer<C, never, A>
CLive
=
import Layer
Layer
.
const effect: <typeof C, never, A>(tag: typeof C, effect: Effect.Effect<{
readonly c: boolean;
}, never, A>) => Layer.Layer<C, never, A> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class C
C
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
c: boolean;
}>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
c: boolean;
}, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
const {
const a: number
a
} = yield*
class A
A
return {
c: boolean
c
:
const a: number
a
> 0 }
})
)
const
const program: Effect.Effect<void, never, B | C>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<B, {
readonly b: string;
}>> | YieldWrap<Context.Tag<C, {
readonly c: boolean;
}>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
yield*
class B
B
yield*
class C
C
})
const
const runnable: Effect.Effect<void, never, never>
runnable
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <void, never, B | C, B | C, never, never>(self: Effect.Effect<void, never, B | C>, layer: Layer.Layer<B | C, never, never>) => Effect.Effect<void, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
const program: Effect.Effect<void, never, B | C>
program
,
import Layer
Layer
.
const merge: <never, never, B, never, never, C>(self: Layer.Layer<B, never, never>, that: Layer.Layer<C, never, never>) => Layer.Layer<B | C, never, never> (+1 overload)

Merges this layer with the specified layer concurrently, producing a new layer with combined input and output types.

@since2.0.0

merge
(
import Layer
Layer
.
const provide: <A, never, B, never, never, A>(self: Layer.Layer<B, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<B, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

@since2.0.0

provide
(
const BLive: Layer.Layer<B, never, A>
BLive
,
const ALive: Layer.Layer<A, never, never>
ALive
),
import Layer
Layer
.
const provide: <A, never, C, never, never, A>(self: Layer.Layer<C, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<C, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

@since2.0.0

provide
(
const CLive: Layer.Layer<C, never, A>
CLive
,
const ALive: Layer.Layer<A, never, never>
ALive
))
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns a Promise that resolves with the result.

Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises. If the effect fails, the returned Promise will be rejected with the error.

@example

import { Effect } from "effect"

// Execute an effect and handle the result with a Promise Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1

// Execute a failing effect and handle the rejection Effect.runPromise(Effect.fail("my error")).catch((error) => { console.error("Effect failed with error:", error) })

@since2.0.0

runPromise
(
const runnable: Effect.Effect<void, never, never>
runnable
)
/*
Output:
timestamp=... level=INFO fiber=#2 message=initialized
*/

Although both BLive and CLive layers require the ALive layer, the ALive layer is instantiated only once. It is shared with both BLive and CLive.

If we don’t want to share a module, we should create a fresh, non-shared version of it through Layer.fresh.

Example

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Context

@since2.0.0

@since2.0.0

Context
,
import Layer
Layer
} from "effect"
class
class A
A
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("A")<
class A
A
, { readonly
a: number
a
: number }>() {}
class
class B
B
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"B">(id: "B") => <Self, Shape>() => Context.TagClass<Self, "B", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("B")<
class B
B
, { readonly
b: string
b
: string }>() {}
class
class C
C
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"C">(id: "C") => <Self, Shape>() => Context.TagClass<Self, "C", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("C")<
class C
C
, { readonly
c: boolean
c
: boolean }>() {}
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{
readonly a: number;
}, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class A
A
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <{
a: number;
}>(value: {
a: number;
}) => Effect.Effect<{
a: number;
}, never, never>

Creates an Effect that succeeds with the provided value.

Use this function to represent a successful computation that yields a value of type A. The effect does not fail and does not require any environmental context.

@example

import { Effect } from "effect"

// Creating an effect that succeeds with the number 42 const success = Effect.succeed(42)

@since2.0.0

succeed
({
a: number
a
: 5 }).
Pipeable.pipe<Effect.Effect<{
a: number;
}, never, never>, Effect.Effect<{
a: number;
}, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{
a: number;
}, never, never>) => Effect.Effect<{
a: number;
}, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tap: <{
a: number;
}, Effect.Effect<void, never, never>>(f: (a: {
a: number;
}) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{
a: number;
}, E, R>) => Effect.Effect<...> (+7 overloads)

@since2.0.0

tap
(() =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using Cause instances.

To adjust the log level, use the Logger.withMinimumLogLevel function.

@example

import { Cause, Effect } from "effect"

const program = Effect.log( "message1", "message2", Cause.die("Oh no!"), Cause.die("Oh uh!") )

// Effect.runFork(program) // Output: // timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no! // Error: Oh uh!"

@since2.0.0

log
("initialized"))
)
)
const
const BLive: Layer.Layer<B, never, A>
BLive
=
import Layer
Layer
.
const effect: <typeof B, never, A>(tag: typeof B, effect: Effect.Effect<{
readonly b: string;
}, never, A>) => Layer.Layer<B, never, A> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class B
B
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
b: string;
}>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
b: string;
}, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
const {
const a: number
a
} = yield*
class A
A
return {
b: string
b
:
var String: StringConstructor
(value?: any) => string

Allows manipulation and formatting of text strings and determination and location of substrings within strings.

String
(
const a: number
a
) }
})
)
const
const CLive: Layer.Layer<C, never, A>
CLive
=
import Layer
Layer
.
const effect: <typeof C, never, A>(tag: typeof C, effect: Effect.Effect<{
readonly c: boolean;
}, never, A>) => Layer.Layer<C, never, A> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class C
C
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
c: boolean;
}>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Context.Tag<A, {
readonly a: number;
}>>, {
c: boolean;
}, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
const {
const a: number
a
} = yield*
class A
A
return {
c: boolean
c
:
const a: number
a
> 0 }
})
)
const
const program: Effect.Effect<void, never, B | C>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Context.Tag<B, {
readonly b: string;
}>> | YieldWrap<Context.Tag<C, {
readonly c: boolean;
}>>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
yield*
class B
B
yield*
class C
C
})
const
const runnable: Effect.Effect<void, never, never>
runnable
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <void, never, B | C, B | C, never, never>(self: Effect.Effect<void, never, B | C>, layer: Layer.Layer<B | C, never, never>) => Effect.Effect<void, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
const program: Effect.Effect<void, never, B | C>
program
,
import Layer
Layer
.
const merge: <never, never, B, never, never, C>(self: Layer.Layer<B, never, never>, that: Layer.Layer<C, never, never>) => Layer.Layer<B | C, never, never> (+1 overload)

Merges this layer with the specified layer concurrently, producing a new layer with combined input and output types.

@since2.0.0

merge
(
import Layer
Layer
.
const provide: <A, never, B, never, never, A>(self: Layer.Layer<B, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<B, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

@since2.0.0

provide
(
const BLive: Layer.Layer<B, never, A>
BLive
,
import Layer
Layer
.
const fresh: <A, never, never>(self: Layer.Layer<A, never, never>) => Layer.Layer<A, never, never>

Creates a fresh version of this layer that will not be shared.

@since2.0.0

fresh
(
const ALive: Layer.Layer<A, never, never>
ALive
)),
import Layer
Layer
.
const provide: <A, never, C, never, never, A>(self: Layer.Layer<C, never, A>, that: Layer.Layer<A, never, never>) => Layer.Layer<C, never, never> (+3 overloads)

Feeds the output services of this builder into the input of the specified builder, resulting in a new builder with the inputs of this builder as well as any leftover inputs, and the outputs of the specified builder.

@since2.0.0

provide
(
const CLive: Layer.Layer<C, never, A>
CLive
,
import Layer
Layer
.
const fresh: <A, never, never>(self: Layer.Layer<A, never, never>) => Layer.Layer<A, never, never>

Creates a fresh version of this layer that will not be shared.

@since2.0.0

fresh
(
const ALive: Layer.Layer<A, never, never>
ALive
))
)
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns a Promise that resolves with the result.

Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises. If the effect fails, the returned Promise will be rejected with the error.

@example

import { Effect } from "effect"

// Execute an effect and handle the result with a Promise Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1

// Execute a failing effect and handle the rejection Effect.runPromise(Effect.fail("my error")).catch((error) => { console.error("Effect failed with error:", error) })

@since2.0.0

runPromise
(
const runnable: Effect.Effect<void, never, never>
runnable
)
/*
Output:
timestamp=... level=INFO fiber=#2 message=initialized
timestamp=... level=INFO fiber=#3 message=initialized
*/

If we don’t provide a layer globally but instead provide them locally, that layer doesn’t support memoization by default.

Example

In the following example, we provided the ALive layer two times locally, and Effect doesn’t memoize the construction of the ALive layer. So, it will be initialized two times:

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Context

@since2.0.0

@since2.0.0

Context
,
import Layer
Layer
} from "effect"
class
class A
A
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("A")<
class A
A
, { readonly
a: number
a
: number }>() {}
const
const Alive: Layer.Layer<A, never, never>
Alive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{
readonly a: number;
}, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class A
A
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <{
a: number;
}>(value: {
a: number;
}) => Effect.Effect<{
a: number;
}, never, never>

Creates an Effect that succeeds with the provided value.

Use this function to represent a successful computation that yields a value of type A. The effect does not fail and does not require any environmental context.

@example

import { Effect } from "effect"

// Creating an effect that succeeds with the number 42 const success = Effect.succeed(42)

@since2.0.0

succeed
({
a: number
a
: 5 }).
Pipeable.pipe<Effect.Effect<{
a: number;
}, never, never>, Effect.Effect<{
a: number;
}, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{
a: number;
}, never, never>) => Effect.Effect<{
a: number;
}, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tap: <{
a: number;
}, Effect.Effect<void, never, never>>(f: (a: {
a: number;
}) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{
a: number;
}, E, R>) => Effect.Effect<...> (+7 overloads)

@since2.0.0

tap
(() =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using Cause instances.

To adjust the log level, use the Logger.withMinimumLogLevel function.

@example

import { Cause, Effect } from "effect"

const program = Effect.log( "message1", "message2", Cause.die("Oh no!"), Cause.die("Oh uh!") )

// Effect.runFork(program) // Output: // timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no! // Error: Oh uh!"

@since2.0.0

log
("initialized"))
)
)
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<{
readonly a: number;
}, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<{
readonly a: number;
}, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <{
readonly a: number;
}, never, A, A, never, never>(self: Effect.Effect<{
readonly a: number;
}, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{
readonly a: number;
}, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
class A
A
,
const Alive: Layer.Layer<A, never, never>
Alive
)
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <{
readonly a: number;
}, never, A, A, never, never>(self: Effect.Effect<{
readonly a: number;
}, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{
readonly a: number;
}, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
class A
A
,
const Alive: Layer.Layer<A, never, never>
Alive
)
})
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns a Promise that resolves with the result.

Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises. If the effect fails, the returned Promise will be rejected with the error.

@example

import { Effect } from "effect"

// Execute an effect and handle the result with a Promise Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1

// Execute a failing effect and handle the rejection Effect.runPromise(Effect.fail("my error")).catch((error) => { console.error("Effect failed with error:", error) })

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Output:
timestamp=... level=INFO fiber=#0 message=initialized
timestamp=... level=INFO fiber=#0 message=initialized
*/

We can memoize a layer manually using the Layer.memoize function. It will return a scoped effect that, if evaluated, will return the lazily computed result of this layer.

Example

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Context

@since2.0.0

@since2.0.0

Context
,
import Layer
Layer
} from "effect"
class
class A
A
extends
import Context

@since2.0.0

@since2.0.0

Context
.
const Tag: <"A">(id: "A") => <Self, Shape>() => Context.TagClass<Self, "A", Shape>

@example

import { Context, Layer } from "effect"

class MyTag extends Context.Tag("MyTag")< MyTag, { readonly myNum: number }

() { static Live = Layer.succeed(this, { myNum: 108 }) }

@since2.0.0

Tag
("A")<
class A
A
, { readonly
a: number
a
: number }>() {}
const
const ALive: Layer.Layer<A, never, never>
ALive
=
import Layer
Layer
.
const effect: <typeof A, never, never>(tag: typeof A, effect: Effect.Effect<{
readonly a: number;
}, never, never>) => Layer.Layer<A, never, never> (+1 overload)

Constructs a layer from the specified effect.

@since2.0.0

effect
(
class A
A
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <{
a: number;
}>(value: {
a: number;
}) => Effect.Effect<{
a: number;
}, never, never>

Creates an Effect that succeeds with the provided value.

Use this function to represent a successful computation that yields a value of type A. The effect does not fail and does not require any environmental context.

@example

import { Effect } from "effect"

// Creating an effect that succeeds with the number 42 const success = Effect.succeed(42)

@since2.0.0

succeed
({
a: number
a
: 5 }).
Pipeable.pipe<Effect.Effect<{
a: number;
}, never, never>, Effect.Effect<{
a: number;
}, never, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<{
a: number;
}, never, never>) => Effect.Effect<{
a: number;
}, never, never>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const tap: <{
a: number;
}, Effect.Effect<void, never, never>>(f: (a: {
a: number;
}) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<{
a: number;
}, E, R>) => Effect.Effect<...> (+7 overloads)

@since2.0.0

tap
(() =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const log: (...message: ReadonlyArray<any>) => Effect.Effect<void, never, never>

Logs one or more messages or error causes at the current log level, which is INFO by default. This function allows logging multiple items at once and can include detailed error information using Cause instances.

To adjust the log level, use the Logger.withMinimumLogLevel function.

@example

import { Cause, Effect } from "effect"

const program = Effect.log( "message1", "message2", Cause.die("Oh no!"), Cause.die("Oh uh!") )

// Effect.runFork(program) // Output: // timestamp=... level=INFO fiber=#0 message=message1 message=message2 cause="Error: Oh no! // Error: Oh uh!"

@since2.0.0

log
("initialized"))
)
)
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const scoped: <void, never, Scope>(effect: Effect.Effect<void, never, Scope>) => Effect.Effect<void, never, never>

Scopes all resources used in this workflow to the lifetime of the workflow, ensuring that their finalizers are run as soon as this workflow completes execution, whether by success, failure, or interruption.

@since2.0.0

scoped
(
import Layer
Layer
.
const memoize: <never, never, A>(self: Layer.Layer<A, never, never>) => Effect.Effect<Layer.Layer<A, never, never>, never, Scope>

Returns a scoped effect that, if evaluated, will return the lazily computed result of this layer.

@since2.0.0

memoize
(
const ALive: Layer.Layer<A, never, never>
ALive
).
Pipeable.pipe<Effect.Effect<Layer.Layer<A, never, never>, never, Scope>, Effect.Effect<void, never, Scope>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<Layer.Layer<A, never, never>, never, Scope>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const andThen: <Layer.Layer<A, never, never>, Effect.Effect<void, never, never>>(f: (a: Layer.Layer<A, never, never>) => Effect.Effect<void, never, never>) => <E, R>(self: Effect.Effect<...>) => Effect.Effect<...> (+3 overloads)

Executes a sequence of two actions, typically two Effects, where the second action can depend on the result of the first action.

The that action can take various forms:

  • a value
  • a function returning a value
  • a promise
  • a function returning a promise
  • an effect
  • a function returning an effect

@example

import { Effect } from "effect"

assert.deepStrictEqual(Effect.runSync(Effect.succeed("aa").pipe(Effect.andThen(1))), 1) assert.deepStrictEqual(Effect.runSync(Effect.succeed("aa").pipe(Effect.andThen((s) => s.length))), 2)

assert.deepStrictEqual(await Effect.runPromise(Effect.succeed("aa").pipe(Effect.andThen(Promise.resolve(1)))), 1) assert.deepStrictEqual(await Effect.runPromise(Effect.succeed("aa").pipe(Effect.andThen((s) => Promise.resolve(s.length)))), 2)

assert.deepStrictEqual(Effect.runSync(Effect.succeed("aa").pipe(Effect.andThen(Effect.succeed(1)))), 1) assert.deepStrictEqual(Effect.runSync(Effect.succeed("aa").pipe(Effect.andThen((s) => Effect.succeed(s.length)))), 2)

@since2.0.0

andThen
((
memoized: Layer.Layer<A, never, never>
memoized
) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<{
readonly a: number;
}, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<{
readonly a: number;
}, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

@since2.0.0

gen
(function* () {
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <{
readonly a: number;
}, never, A, A, never, never>(self: Effect.Effect<{
readonly a: number;
}, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{
readonly a: number;
}, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
class A
A
,
memoized: Layer.Layer<A, never, never>
memoized
)
yield*
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const provide: <{
readonly a: number;
}, never, A, A, never, never>(self: Effect.Effect<{
readonly a: number;
}, never, A>, layer: Layer.Layer<A, never, never>) => Effect.Effect<{
readonly a: number;
}, never, never> (+9 overloads)

Splits the context into two parts, providing one part using the specified layer/context/runtime and leaving the remainder R0

@since2.0.0

provide
(
class A
A
,
memoized: Layer.Layer<A, never, never>
memoized
)
})
)
)
)
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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

Executes an effect and returns a Promise that resolves with the result.

Use runPromise when working with asynchronous effects and you need to integrate with code that uses Promises. If the effect fails, the returned Promise will be rejected with the error.

@example

import { Effect } from "effect"

// Execute an effect and handle the result with a Promise Effect.runPromise(Effect.succeed(1)).then(console.log) // Output: 1

// Execute a failing effect and handle the rejection Effect.runPromise(Effect.fail("my error")).catch((error) => { console.error("Effect failed with error:", error) })

@since2.0.0

runPromise
(
const program: Effect.Effect<void, never, never>
program
)
/*
Output:
timestamp=... level=INFO fiber=#0 message=initialized
*/