You may have noticed something odd: we are using PokeApiUrlLive
twice when composing MainLayer
.
const MainLayer = Layer.mergeAll(
PokeApi.Live,
PokemonCollection.Live,
BuildPokeApiUrl.Live.pipe(Layer.provide(PokeApiUrl.Live)),
PokeApiUrl.Live,
);
Is this a problem? Will the layer be created more than once?
This is not a problem at all since layers in effect are memoized. This means that each layer will be created only once and the same instance will be provided every time.
This makes composing layers way more convenient.
In fact, it's good practice to directly provide the required dependencies directly when defining a Layer
inside Live
:
export class BuildPokeApiUrl extends Context.Tag("BuildPokeApiUrl")<
BuildPokeApiUrl,
({ name }: { name: string }) => string
>() {
static readonly Live = Layer.effect(
this,
Effect.gen(function* () {
const pokeApiUrl = yield* PokeApiUrl;
return ({ name }) => `${pokeApiUrl}/${name}`;
})
).pipe(
// `provide` dependency layers directly inside `Live`
Layer.provide(PokeApiUrl.Live)
);
}
With these MainLayer
simply requires a single mergeAll
of all the layers necessary to run the program:
const MainLayer = Layer.mergeAll(
PokeApi.Live,
PokemonCollection.Live,
BuildPokeApiUrl.Live,
PokeApiUrl.Live
);
That's the full power of the effect composability model! We can swap layers by changing a single line of code. This allows to mix and compose different implementations with ease, all while keeping full type safety.
Furthermore, we can again focus on a single service implementation without bothering with its dependencies or errors.
Everything is collected and provided at the end. Making changes to the codebase becomes easier since we do not need to read or understand everything, but we can instead focus on a single service.
Maintaining the app also becomes easier since every breaking change will cause a type issue that the typescript compiler will guide us to solve where needed.
This is full type safety! This is the point of no return: once you understand how powerful this model is you won't ever come back!