| title | Avoid Long Chains of .andThen; Use Generators Instead | |||||
|---|---|---|---|---|---|---|
| id | avoid-long-andthen-chains | |||||
| skillLevel | intermediate | |||||
| applicationPatternId | domain-modeling | |||||
| summary | Prefer Effect.gen over long chains of .andThen for sequential logic to improve readability and maintainability. | |||||
| tags |
|
|||||
| rule |
|
|||||
| related |
|
|||||
| author | Dillon Mulroy | |||||
| lessonOrder | 2 |
For sequential logic involving more than two steps, prefer Effect.gen over
chaining multiple .andThen or .flatMap calls.
Effect.gen provides a flat, linear code structure that is easier to read and
debug than deeply nested functional chains.
import { Effect } from "effect";
// Define our steps with logging
const step1 = (): Effect.Effect<number> =>
Effect.succeed(42).pipe(Effect.tap((n) => Effect.log(`Step 1: ${n}`)));
const step2 = (a: number): Effect.Effect<string> =>
Effect.succeed(`Result: ${a * 2}`).pipe(
Effect.tap((s) => Effect.log(`Step 2: ${s}`))
);
// Using Effect.gen for better readability
const program = Effect.gen(function* () {
const a = yield* step1();
const b = yield* step2(a);
return b;
});
// Run the program
const programWithLogging = Effect.gen(function* () {
const result = yield* program;
yield* Effect.log(`Final result: ${result}`);
return result;
});
Effect.runPromise(programWithLogging);Explanation:
Generators keep sequential logic readable and easy to maintain.
import { Effect } from "effect";
declare const step1: () => Effect.Effect<any>;
declare const step2: (a: any) => Effect.Effect<any>;
step1().pipe(Effect.flatMap((a) => step2(a))); // Or .andThenChaining many .flatMap or .andThen calls leads to deeply nested,
hard-to-read code.