<Impl, const S extends Spec, Ctx>(
impl: Impl,
spec: S,
context: Context.Context<Ctx>
): ProvidedContext<Impl, Ctx>Provide a Context.Context to every Effect method of an impl — the one-liner that replaces a
repetitive per-method Effect.provideContext(...) wrapping. One-liner over mapEffects; the
result subtracts the provided context Ctx from each method's requirement (see
ProvidedContext) — R → Exclude<R, Ctx> — so a worker-R-carrying impl whose context fully
covers R becomes the R-free shape ImplOf expects, and a method needing more than Ctx
provides keeps a residual requirement (caught at the ImplOf assignment) rather than a false never.
Providing the context to a method that carries no R is a harmless no-op, so it applies uniformly.
Stream and Subscribable members are left untouched.
const context = yield* Effect.context<R | RR>();
return Hyperlink.provideContext(impl, MyTag[Hyperlink.specSym], context);export const const provideContext: <
Impl,
S extends Spec,
Ctx
>(
impl: Impl,
spec: S,
context: Context.Context<Ctx>
) => ProvidedContext<Impl, Ctx>
Provide a
Context.Context
to every Effect method of an impl — the one-liner that replaces a
repetitive per-method Effect.provideContext(...) wrapping. One-liner over
mapEffects
; the
result subtracts the provided context Ctx from each method's requirement (see
ProvidedContext
) — R → Exclude<R, Ctx> — so a worker-R-carrying impl whose context fully
covers R becomes the R-free shape
ImplOf
expects, and a method needing more than Ctx
provides keeps a residual requirement (caught at the ImplOf assignment) rather than a false never.
Providing the context to a method that carries no R is a harmless no-op, so it applies uniformly.
Stream
and
Subscribable
members are left untouched.
const context = yield* Effect.context<R | RR>();
return Hyperlink.provideContext(impl, MyTag[Hyperlink.specSym], context);
provideContext = <function (type parameter) Impl in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Impl, const function (type parameter) S in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>S extends Spec, function (type parameter) Ctx in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Ctx>(
impl: Implimpl: function (type parameter) Impl in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Impl,
spec: const S extends Specspec: function (type parameter) S in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>S,
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 <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Ctx>,
): type ProvidedContext<T, Ctx> = T extends Subscribable<infer A> ? Subscribable<A> : T extends Stream.Stream<infer A, infer E, infer R> ? Stream.Stream<A, E, R> : T extends (...args: infer Args) => Effect.Effect<infer S, infer E, infer R> ? (...args: Args) => 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]: ProvidedContext<...>; } : TRemove the requirement channel R from every Effect method in an impl shape — the per-method-precise
result of
provideContext
. Mirrors Store.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 (and a
later ImplOf assignment catches it) instead of being silently claimed never. A method
(...a) => Effect<S, E, R> → (...a) => Effect<S, E, Exclude<R, Ctx>>; a bare Effect<S, E, R> →
Effect<S, E, Exclude<R, Ctx>>; a
Subscribable
(a
ref
field's impl) and a
Stream
(a stream field's impl, or a group's live) pass through untouched; a nested method group recurses.
ProvidedContext<function (type parameter) Impl in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Impl, function (type parameter) Ctx in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Ctx> =>
const mapEffects: <
Impl,
S extends Spec,
Out = Impl
>(
impl: Impl,
spec: S,
transform: (
effect: Effect.Effect<unknown, never, never>
) => Effect.Effect<unknown, never, never>
) => Out
The generic impl-transform primitive — the Hyperlink counterpart to Store.mapEffects. Walk impl
per its spec (
flattenSpec
keys aligned onto the impl via
flattenImpl
) and pass each
Effect method's returned
Effect
through transform, then re-nest (
nestService
). A
stream: true leaf — a
Hyperlink.stream
member (a
Stream
impl) or a
ref
field
(a
Subscribable
impl) — is left untouched, as is a
LocalMethod
leaf.
transform is applied uniformly; whether it changes types is expressed through the result:
- Type-preserving transforms (
withSpan / retry) leave the type unchanged — Out defaults to
Impl.
- Type-changing transforms (stripping
R, like
provideContext
) supply an explicit Out
computed per method by a mapped type (e.g.
ProvidedContext
).
mapEffects<function (type parameter) Impl in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Impl, function (type parameter) S in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>S, type ProvidedContext<T, Ctx> = T extends Subscribable<infer A> ? Subscribable<A> : T extends Stream.Stream<infer A, infer E, infer R> ? Stream.Stream<A, E, R> : T extends (...args: infer Args) => Effect.Effect<infer S, infer E, infer R> ? (...args: Args) => 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]: ProvidedContext<...>; } : TRemove the requirement channel R from every Effect method in an impl shape — the per-method-precise
result of
provideContext
. Mirrors Store.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 (and a
later ImplOf assignment catches it) instead of being silently claimed never. A method
(...a) => Effect<S, E, R> → (...a) => Effect<S, E, Exclude<R, Ctx>>; a bare Effect<S, E, R> →
Effect<S, E, Exclude<R, Ctx>>; a
Subscribable
(a
ref
field's impl) and a
Stream
(a stream field's impl, or a group's live) pass through untouched; a nested method group recurses.
ProvidedContext<function (type parameter) Impl in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Impl, function (type parameter) Ctx in <Impl, const S extends Spec, Ctx>(impl: Impl, spec: S, context: Context.Context<Ctx>): ProvidedContext<Impl, Ctx>Ctx>>(impl: Implimpl, spec: const S extends Specspec, (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,
);