Context.get
Building up a context is not much use unless we are able to retrieve things from it. The unsafeMap
is, as the name suggests, not the preferred way to access services from a context.
Context.get(context, tag)
returns the service implementation for the given tag from the given context.
import { Context } from "effect";
export class ActiveUser extends Context.Tag("@myapp/ActiveUser")<
ActiveUser,
{ name: string }
>() {}
const Greeting = Context.GenericTag<"GreetingId", string>("@myapp/Greeting");
const initial: Context.Context<"GreetingId"> = Greeting.context("Welcome");
const combined: Context.Context<"GreetingId" | ActiveUser> = initial.pipe(
Context.add(ActiveUser, { name: "Jane" }),
);
const jane = Context.get(combined, ActiveUser);
const welcome = combined.pipe(Context.get(Greeting));
console.log(welcome, jane.name);
Getting a tag from context is type-safe. Note that in the previous example, jane.name
is correctly recognised as a string (but welcome.name
would not pass type-checking).
Note that just like with Effect
s, there is a dual API for Context
, to make it easier to support piping operations.
To call the function immediately, pass all arguments with the Context
(“self”) as the first argument.
To defer evaluation and return a function instead, pass all arguments except “self”.
Context.get(context, tag); // self-first
Context.get(tag)(context); // self-last
Context.add(context, tag, service); // self-first
Context.add(tag, service)(context); // self-last
Context is also type-safe in its keys. You cannot get a service that is not available from that Context.
Context.get(initial, ActiveUser);
// error TS2769: No overload matches this call.
// Overload 1 of 4, '(self: Context<"GreetingId">, tag: Reference<unknown, unknown>): unknown', gave the following error.
// Argument of type 'typeof ActiveUser' is not assignable to parameter of type 'Reference<unknown, unknown>'.
// Type 'typeof ActiveUser' is missing the following properties from type 'Reference<unknown, unknown>': defaultValue, [ReferenceTypeId]
// Overload 2 of 4, '(self: Context<"GreetingId">, tag: Tag<"GreetingId", any>): any', gave the following error.
// Argument of type 'typeof ActiveUser' is not assignable to parameter of type 'Tag<"GreetingId", any>'.
// Types of property 'Identifier' are incompatible.
// Type 'ActiveUser' is not assignable to type '"GreetingId"'.
(Recall that adding an ActiveUser
to initial
will create a new Context
, leaving initial
untouched.)
Let’s recap:
Context.get(context, tag)
can retrieve a service from a context- The type of the returned value will match the service type of the tag passed in
- It is a compile-time error to get a tag that is not in the context
- Operations on Context are plain (non-effectful) operations