0Pricing
TypeScript Academy · Lesson

Composing Effects

Chain and combine effects with pipe and generators.

Composing Effects is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Composing Effects

Effects are values, so you build programs by composing them. The core tools are Effect.pipe, Effect.map, Effect.flatMap, and the generator-based Effect.gen syntax.

pipe: Threading Through Functions

pipe passes an effect through a series of transformations left to right, avoiding deep nesting.

import { Effect, pipe } from "effect";

const program = pipe(
  Effect.succeed(2),
  Effect.map((n) => n + 1),
  Effect.map((n) => n * 10)
);
// Effect<number, never, never> producing 30

map: Transforming the Success Value

Effect.map applies a pure function to the success value, leaving error and requirement channels untouched.

import { Effect } from "effect";

const doubled = Effect.map(Effect.succeed(21), (n) => n * 2);
// Effect<number, never, never>

flatMap: Sequencing Effects

When the next step is itself an effect, use flatMap (also called chain). It runs the first effect, then feeds its value into a function returning another effect.

import { Effect, pipe } from "effect";

const getId = Effect.succeed(1);
const loadUser = (id: number) => Effect.succeed({ id, name: "Ada" });

const program = pipe(getId, Effect.flatMap(loadUser));
// Effect<{ id: number; name: string }, never, never>

map vs flatMap

Use map when your function returns a plain value; use flatMap when it returns an effect. Using map with an effect-returning function leaves you with a nested effect.

Channels Accumulate

As you sequence effects, their error types union together and their requirements union together. The composed type reflects everything that can fail and everything that is needed.

// Effect<A, E1, R1> then Effect<B, E2, R2>
// => Effect<B, E1 | E2, R1 | R2>

Effect.gen: Generator Syntax

Effect.gen lets you write sequential effect code that reads like async/await, using yield* to unwrap each effect.

import { Effect } from "effect";

const program = Effect.gen(function* () {
  const id = yield* Effect.succeed(1);
  const user = yield* Effect.succeed({ id, name: "Ada" });
  return user.name;
});
// Effect<string, never, never>

gen vs pipe

gen is clearer for linear, multi-step flows with intermediate variables; pipe shines for short transformation chains. They interoperate freely.

Combining Independent Effects

Effect.all runs multiple effects and collects their results, accumulating errors and requirements from all of them.

import { Effect } from "effect";

const both = Effect.all([Effect.succeed(1), Effect.succeed("x")]);
// Effect<[number, string], never, never>

Still Lazy

All of this only describes the program. Nothing executes until you run it at the edge with Effect.runPromise or Effect.runSync.

import { Effect } from "effect";
// const result = await Effect.runPromise(program);

Why This Matters

Composition is what makes effects practical: you assemble small, typed pieces into large programs while the compiler tracks every error and dependency. map, flatMap, pipe, and gen are the everyday verbs of Effect code.

Quick Check

Check your understanding of composing effects.

Recap

You compose effects with map (transform success values), flatMap (sequence effect-returning steps), pipe (thread through transformations), and Effect.gen (await-like generator syntax). Error and requirement channels accumulate as unions, and nothing runs until you execute at the edge.

Frequently asked questions

Is the “Composing Effects” lesson free?

Yes — the full text of “Composing Effects” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Composing Effects”?

Chain and combine effects with pipe and generators. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Composing Effects” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Why Effect Systems Matter
  2. The Effect Type
  3. Composing Effects
  4. Error Channels and Dependencies
← Back to TypeScript Academy