effect-getting-started
effect-getting-started copied to clipboard
Example apps to get started using all the features of effect: Context, Layer, Runtime, Scope and more 🪄
How to effect
This project is part of my weekly newsletter at sandromaglione.com.
![sandromaglione.com Newsletter weekly project](https://www.sandromaglione.com/static/images/newsletter_banner.webp)
Project structure
This is a collection of examples of how to use effect
.
This is a deep dive exploration of the features and internals offered by effect
.
How to use
Install:
pnpm install
Then you can run each script (take a look at package.json
for the list of all the scripts you can run):
pnpm run index
Note: The convention is that files that start with a lowercase letter are runnable scripts
Take a look also at test
.
Notes
Base64
No need to install extra libraries like js-base64
. The Encoding
module provides encoding/decoding of base64.
Context
(Tag
)
Inside GlobalValue
Effect stores a globalStore
of type Map<unknown, any>
.
Inside this store the Context
module registers a tagRegistry
:
const tagRegistry = globalValue("effect/Context/Tag/tagRegistry", () => new Map<any, C.Tag<any, any>>())
Inside this registry Effect collects all Tag
s, created using Context.Tag
by calling the internal makeTag
.
[!Note] When you pass an
identifier
toContext.Tag
you specify a key for thetagRegistry
. Effect checks the registry when accessing and creating a new tag.
A Tag
is an instance of Pipeable
. This allows to chain .pipe
to an instance of Tag
to extract the methods of a service:
interface Base64Service {
readonly decode: (
source: string
) => Effect.Effect<never, Base64DecodeError, string>;
}
export const Base64Service = Context.Tag<Base64Service>("@app/Base64Service");
/** Use `pipe` to extract the methods from the service 👆 */
const result = Base64.Base64Service.pipe(
Effect.flatMap((base64) => base64.decode("Zm9vYmFy")),
Effect.provide(Base64.Base64ServiceLive), // 👈 Then provide a valid instance
Effect.runSync
);
Tag
(Context
) is also a valid instance of Effect
. This allows to use methods such as flatMap
.
ContextProto
An instance of Context
is created by copying a context prototype (using Object.create
inside the internal makeContext
)
Iterable
The Iteration protocols define an Iterable
interface:
interface Iterator<T, TReturn = any, TNext = undefined> {
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return?(value?: TReturn): IteratorResult<T, TReturn>;
throw?(e?: any): IteratorResult<T, TReturn>;
}
interface Iterable<T> {
[Symbol.iterator](): Iterator<T>;
}
The Effect
type defines an iterator. This allows to use yield*
in Effect.gen
(EffectGen
and SingleShotGen
).
This is also used by Effect to define methods such as map
.