When organizing the dependencies in a complex app services are not enough anymore. We soon encounter problems with interdependencies and providing services that depend on each other.
Effect offers an better abstraction for this: Layer
.
Let's see why this is needed.
Adding more services
We need something more complex to understand the point of Layer
.
Let's add some services then.
With effect a service does not need to be a collection of methods. Anything can be wrapped with
Context
to create a service.
For example we can create a PokemonCollection
service that contains a non-empty list of string
:
import { Context, type Array } from "effect";
export class PokemonCollection extends Context.Tag("PokemonCollection")<
PokemonCollection,
/// 👇 A list of names of your favorite Pokémon
Array.NonEmptyArray<string>
>() {}
We use
Array.NonEmptyArray
from theArray
module of effect. This requiresPokemonCollection
to have at least 1 Pokémon in the list.
Array
is out of scope for this course. It's really handy, I suggest you to explore it on the docs!
A service can also be a single function. We can create a BuildPokeApiUrl
service that constructs the PokéApi url endpoint to request a Pokémon:
import { Context } from "effect";
export class BuildPokeApiUrl extends Context.Tag("BuildPokeApiUrl")<
BuildPokeApiUrl,
/// 👇 A single function
(props: { name: string }) => string
>() {}
What about a service for a single string
? We can do this as well:
import { Context } from "effect";
export class PokeApiUrl extends Context.Tag("PokeApiUrl")<
PokeApiUrl,
// 👇 Even a single `string` works
string
>() {}