Skip to content

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 for Effect.fn, and the small set of things you should never do inside a generator (no async/await, no try/catch, no Date.now).
  • Calling APIs. Effect functions are “dual” — they work both with pipe and as standalone calls. Knowing which form to use where keeps pipelines readable.
  • Modeling data. Branded types let you turn structurally identical primitives (a UserId and an OrderId are both number) into distinct types the compiler will keep apart.
  • Guidelinesgen vs fn, avoiding async/await and try/catch, preferring services over globals, and using Clock instead of Date.
  • Dual APIs — the data-first and data-last variants of Effect functions and the pipe convention 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.