Code Style
Effect is a large library, but most of it composes around a small set of conventions. Once those conventions are second nature, code written by different people on different teams reads the same way — and the compiler catches far more mistakes for you. This section collects the style rules that the Effect codebase itself follows, distilled into practical guidance.
The conventions fall into three groups:
- Writing effects. How to structure imperative-looking code with
Effect.gen, when to reach forEffect.fn, and the small set of things you should never do inside a generator (noasync/await, notry/catch, noDate.now). - Calling APIs. Effect functions are “dual” — they work both with
pipeand as standalone calls. Knowing which form to use where keeps pipelines readable. - Modeling data. Branded types let you turn structurally identical
primitives (a
UserIdand anOrderIdare bothnumber) into distinct types the compiler will keep apart.
In this section
Section titled “In this section”- Guidelines —
genvsfn, avoidingasync/awaitandtry/catch, preferring services over globals, and usingClockinstead ofDate. - Dual APIs — the data-first and data-last variants
of Effect functions and the
pipeconvention that ties them together. - Branded Types — when and how to use branded/nominal types to prevent mixing values that share a runtime representation.
These pages assume you are comfortable with the basics from Effect Essentials and Services & Layers. The rules here are not arbitrary: each one exists because the alternative silently breaks tracing, type inference, or testability.