<Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(
effects: Effects,
context: Context.Context<Ctx>
): StoreProvidedContext<Effects, Ctx>Provide a Context.Context to every method of an effects object — the one-liner
that replaces a repetitive per-method Effect.provideContext(...) wrapping. One-liner over
mapEffects, exactly parallel to catchWriteErrors; the result subtracts the
provided context Ctx from each method's requirement (see StoreProvidedContext) — R →
Exclude<R, Ctx> — so an effects object whose only requirement is Storage becomes the
Storage-free shape a downstream consumer expects, while a method needing more than Ctx provides
keeps a residual requirement (caught at the assignment) rather than a false never. Providing the
context to a method that carries no matching R is a harmless no-op, so it applies uniformly.
const storageContext = yield* Effect.context<Store.Storage>();
const store = Store.provideContext(storeEffects, storageContext); // methods become Effect<void>export const const provideContext: <
Effects extends StoreEffectsVariance<StoreContractValue>,
Ctx
>(
effects: Effects,
context: Context.Context<Ctx>
) => StoreProvidedContext<Effects, Ctx>
Provide a
Context.Context
to every method of an
effects
object — the one-liner
that replaces a repetitive per-method Effect.provideContext(...) wrapping. One-liner over
mapEffects
, exactly parallel to
catchWriteErrors
; the result subtracts the
provided context Ctx from each method's requirement (see
StoreProvidedContext
) — R →
Exclude<R, Ctx> — so an effects object whose only requirement is
Storage
becomes the
Storage-free shape a downstream consumer expects, while a method needing more than Ctx provides
keeps a residual requirement (caught at the assignment) rather than a false never. Providing the
context to a method that carries no matching R is a harmless no-op, so it applies uniformly.
const storageContext = yield* Effect.context<Store.Storage>();
const store = Store.provideContext(storeEffects, storageContext); // methods become Effect<void>
provideContext = <
function (type parameter) Effects in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Effects extends interface StoreEffectsVariance<out C extends StoreContractValue>Variance carrier for the
effects
brand — mirrors Effect's Stream.Variance. C is
covariant (Effect's (_: never) => C encoding), so a specific contract's effects satisfy the wide
StoreEffectsVariance<StoreContractValue> constraint that
mapEffects
/
catchWriteErrors
take.
StoreEffectsVariance<import StoreContractValueStoreContractValue>,
function (type parameter) Ctx in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Ctx,
>(
effects: Effects extends StoreEffectsVariance<StoreContractValue>effects: function (type parameter) Effects in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Effects,
context: Context.Context<Ctx>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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;
}
context: import ContextContext.interface Context<in Services>Immutable collection of service implementations used for dependency
injection in Effect programs.
Details
The type parameter tracks the service identifiers available in the context.
At runtime, services are stored by each key's string key.
Example (Creating a context with multiple services)
import { Context } from "effect"
// Create a context with multiple services
const Logger = Context.Service<{ log: (msg: string) => void }>("Logger")
const Database = Context.Service<{ query: (sql: string) => string }>(
"Database"
)
const context = Context.make(Logger, {
log: (msg: string) => console.log(msg)
})
.pipe(Context.add(Database, { query: (sql) => `Result: ${sql}` }))
Context<function (type parameter) Ctx in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Ctx>,
): type StoreProvidedContext<T, Ctx> =
T extends (
...args: infer A
) => Effect.Effect<infer S, infer E, infer R>
? (
...args: A
) => Effect.Effect<S, E, Exclude<R, Ctx>>
: T extends Effect.Effect<
infer S,
infer E,
infer R
>
? Effect.Effect<S, E, Exclude<R, Ctx>>
: T extends (
...args: ReadonlyArray<never>
) => unknown
? T
: T extends object
? {
readonly [K in keyof T]: StoreProvidedContext<
T[K],
Ctx
>
}
: T
Remove the requirement channel Ctx from every method in a resolved-effects shape, recursing into
nested sub-trees — the per-method-precise result of
provideContext
. Mirrors
CatchWriteError
, but subtracts the provided context Ctx from each method's requirement
rather than catching an error — sound like Effect.provideContext (R → Exclude<R, Ctx>), so a
requirement the context does not cover survives as a residual (caught at a later assignment)
instead of being silently claimed never. A write method
(...a) => Effect<S, E, R> → (...a) => Effect<S, E, Exclude<R, Ctx>>; a bare
Effect
custom
member is subtracted too; the
StoreEffectsVariance
brand's non-effect members pass through
(the function-passthrough branch keeps _C intact); a sub-tree recurses.
StoreProvidedContext<function (type parameter) Effects in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Effects, function (type parameter) Ctx in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Ctx> =>
const mapEffects: <
Effects extends StoreEffectsVariance<StoreContractValue>,
Out = Effects
>(
effects: Effects,
transform: (
effect: Effect.Effect<unknown, never, never>
) => Effect.Effect<unknown, never, never>
) => Out
The generic transform primitive: walk every method on a
effects
object (nested shape
leaves + custom methods) and pass each method's returned
Effect
through transform, then
re-nest and re-stamp the
TypeId
brand. Composes with pipe.
transform is applied uniformly; whether it changes types is expressed through the result:
- Type-preserving transforms (
withSpan / retry / timed, whose signature is
Effect<A, E, R> → Effect<A, E, R>) leave the type unchanged — Out defaults to Effects.
- Type-changing transforms (narrowing
E, like
catchWriteErrors
) supply an explicit
Out computed per method by a mapped type (e.g.
CatchWriteError
), so the change flows
through each method precisely.
mapEffects<function (type parameter) Effects in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Effects, type StoreProvidedContext<T, Ctx> =
T extends (
...args: infer A
) => Effect.Effect<infer S, infer E, infer R>
? (
...args: A
) => Effect.Effect<S, E, Exclude<R, Ctx>>
: T extends Effect.Effect<
infer S,
infer E,
infer R
>
? Effect.Effect<S, E, Exclude<R, Ctx>>
: T extends (
...args: ReadonlyArray<never>
) => unknown
? T
: T extends object
? {
readonly [K in keyof T]: StoreProvidedContext<
T[K],
Ctx
>
}
: T
Remove the requirement channel Ctx from every method in a resolved-effects shape, recursing into
nested sub-trees — the per-method-precise result of
provideContext
. Mirrors
CatchWriteError
, but subtracts the provided context Ctx from each method's requirement
rather than catching an error — sound like Effect.provideContext (R → Exclude<R, Ctx>), so a
requirement the context does not cover survives as a residual (caught at a later assignment)
instead of being silently claimed never. A write method
(...a) => Effect<S, E, R> → (...a) => Effect<S, E, Exclude<R, Ctx>>; a bare
Effect
custom
member is subtracted too; the
StoreEffectsVariance
brand's non-effect members pass through
(the function-passthrough branch keeps _C intact); a sub-tree recurses.
StoreProvidedContext<function (type parameter) Effects in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Effects, function (type parameter) Ctx in <Effects extends StoreEffectsVariance<StoreContractValue>, Ctx>(effects: Effects, context: Context.Context<Ctx>): StoreProvidedContext<Effects, Ctx>Ctx>>(effects: Effects extends StoreEffectsVariance<StoreContractValue>effects, (effect: Effect.Effect<unknown, never, never>(parameter) effect: {
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;
}
effect) =>
import EffectEffect.const provideContext: <unknown, unknown, unknown, Ctx>(self: Effect.Effect<unknown, unknown, unknown>, context: Context.Context<Ctx>) => Effect.Effect<unknown, unknown, Exclude<unknown, Ctx>> (+1 overload)Provides a context to an effect, fulfilling its service requirements.
Details
This function provides multiple services at once by supplying a context
that contains all the required services. It removes the provided services
from the effect's requirements, making them available to the effect.
Example (Providing a complete context)
import { Context, Effect } from "effect"
// Define service keys
const Logger = Context.Service<{
log: (msg: string) => void
}>("Logger")
const Database = Context.Service<{
query: (sql: string) => string
}>("Database")
// Create a context with multiple services
const context = Context.make(Logger, { log: console.log })
.pipe(Context.add(Database, { query: () => "result" }))
// An effect that requires both services
const program = Effect.gen(function*() {
const logger = yield* Effect.service(Logger)
const db = yield* Effect.service(Database)
logger.log("Querying database")
return db.query("SELECT * FROM users")
})
const provided = Effect.provideContext(program, context)
provideContext(effect: Effect.Effect<unknown, never, never>(parameter) effect: {
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;
}
effect as any, context: Context.Context<Ctx>(parameter) context: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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;
}
context) as any,
);