In Context.merge (24)
we saw how to combine two contexts. Context.mergeAll is similar, but it allows passing an arbitrary number of contexts in as the argument.
import { Context } from "effect";
class One extends Context.Tag("One")<One, 1>() {}class Two extends Context.Tag("Two")<Two, 2>() {}class Three extends Context.Tag("Three")<Three, 3>() {}
// ┌─── Context.Context<One | Two | Three>// ▼const merged = Context.mergeAll( Context.make(One, 1), Context.make(Two, 2), Context.make(Three, 3));We can implement mergeAll using Context.merge (24)
and Context.empty (22)
. The type signature makes this appear much more complex than it is. This is a common functional programming technique building on mathematical induction. If we know how to combine two items, and we know how to construct a “base”/“empty” item, then we can combine an array of items recursively.
const mergeAll = <T extends Array<unknown>>( ...ctxs: [...{ [K in keyof T]: Context.Context<T[K]> }]): Context.Context<T[number]> => ctxs.reduce(Context.merge, Context.empty() as Context.Context<T[number]>);Let’s recap:
Context.mergeAllcombines many Contexts- It returns a new, larger Context
- It does not mutate the Contexts passed in