Effect Essentials
An Effect<A, E, R> is a lazy, immutable description of a program. It says: when
run, this computation may succeed with a value of type A, fail with an
error of type E, and requires a set of services R to be provided. Nothing
happens until you hand the description to a runtime (see Runtime) -
building effects is pure, running them is the side effect.
This section covers the everyday mechanics of writing that description: the two
ways to author effectful code, how to lift existing values and APIs into
Effect, and how to sequence and branch between effects.
import { Effect } from "effect"
// A small program: take a number, double it, log it, return it.const program = Effect.gen(function*() { const n = yield* Effect.succeed(21) const doubled = n * 2 yield* Effect.log(`Result: ${doubled}`) return doubled})
// `program` is just a value - a description. Running it produces the effect.Effect.runFork(program)How to write Effect code
Section titled “How to write Effect code”There are two idiomatic styles, and you will mix them constantly.
-
Effect.genlets you write effectful code in an imperative,async/await-like style. Youyield*an effect to get its success value, and the generator threads errors and services through for you. Reach for it whenever a computation has several sequential steps or local variables. -
pipeand combinators (Effect.map,Effect.flatMap,Effect.tap, …) compose effects as data transformations. This style shines for short transformations and for attaching cross-cutting behaviour (logging, spans, retries) to an existing effect.
When you write a function that returns an Effect, do not write a plain
function that returns Effect.gen(...). Use Effect.fn("name") instead - it
gives you the generator syntax plus an automatic tracing span and better stack
traces.
In this section
Section titled “In this section”- Using generators - write imperative-style
effect code with
Effect.genandyield*. - Effect.fn - the right way to define functions that return effects, with named spans.
- Creating effects - lift plain values, sync
code, promises, nullable values, and callbacks into
Effect. - Building pipelines - compose effects with
pipe:map,flatMap,andThen,tap,as. - Control flow - conditional and looping
combinators:
when,forEach,whileLoop, and friends.
Once you are comfortable here, move on to Error Management, Services & Layers, and Runtime.