Effect Foundations & Style
Purpose: Provide a compact, go-to checklist for writing idiomatic Effect TypeScript with data-first pipe style, minimal imperative code, and strong typing. Optimized for a coding agent with limited context.
Triggers
-
New Effect implementation or refactor
-
Selecting map/flatMap/andThen/tap operators
-
Converting promise/callback to Effect
When to use
-
You’re unsure which operator to pick (map vs flatMap vs andThen vs tap)
-
You need a minimal template for sequential vs parallel code
-
You want to keep error and context channels explicit (Effect<E, A, R> )
Checklist (Do First)
-
Prefer data-first .pipe() style for readability
-
Use Effect.gen for sequential logic; Effect.all for parallelism
-
Lift values with Effect.succeed , failures with Effect.fail
-
Declare errors as Data.TaggedError and recover with catchTag(s)
-
Keep effects small, composable, and typed—avoid any
-
If R (requirements) is not never , provide layers explicitly
Minimal Patterns
- Creation
const value = Effect.succeed(42) const failure = Effect.fail(new MyError())
- Transform
const result = value.pipe(
Effect.map((n) => n * 2),
Effect.tap((n) => Effect.log(n=${n}))
)
- Sequential
const program = Effect.gen(function* () { const a = yield* getA() const b = yield* getB(a) return b })
- Parallel
const both = yield* Effect.all([left(), right()], { concurrency: "unbounded" })
Operator Selection Guide
-
Map value: Effect.map
-
Chain effect: Effect.flatMap
-
Ignore previous result: Effect.andThen
-
Side-effect only: Effect.tap
-
Provide context: Effect.provide /layers (see layers skill)
-
Combine layers: Layer.merge , Layer.provide
Key APIs (intuition)
-
Effect.gen : write sequential code with yield* for each Effect
-
Effect.all(values, { concurrency }) : run independent Effects concurrently
-
Effect.catchTags(...) : recover only specific typed errors
-
Layer.merge(a, b) : compose dependencies once, reuse everywhere
-
Effect.runPromise(...) : bridge Effects to async workflows
Real-world snippet: Branching with Match and TaggedError
import { Effect, Match, Data } from "effect"
class UnsupportedPlatformError extends Data.TaggedError("UnsupportedPlatformError")<{ readonly platform: string readonly arch: string }>{}
const detectPlatform = (rawPlatform: string, rawArch: string) => Effect.gen(function* () { const platform = yield* Match.value(rawPlatform).pipe( Match.when("darwin", () => Effect.succeed("darwin" as const)), Match.when("linux", () => Effect.succeed("linux" as const)), Match.orElse(() => Effect.fail(new UnsupportedPlatformError({ platform: rawPlatform, arch: rawArch }))) ) const arch = yield* Match.value(rawArch).pipe( Match.when("x64", () => Effect.succeed("x64" as const)), Match.when("arm64", () => Effect.succeed("aarch64" as const)), Match.when("aarch64", () => Effect.succeed("aarch64" as const)), Match.orElse(() => Effect.fail(new UnsupportedPlatformError({ platform: rawPlatform, arch: rawArch }))) ) return { platform, arch } })
Recovery (Quick)
program.pipe( Effect.catchTag("DomainError", () => Effect.succeed(fallback)), Effect.catchAll((e) => Effect.fail(new WrappedError({ cause: e }))) )
Tooling Steps (with effect-engineer)
-
Grep local examples: Effect.gen , Effect.all , .pipe(
-
Search docs MCP for operator specifics when unsure
-
Consult EffectPatterns for canonical idioms (https://github.com/PaulJPhilp/EffectPatterns)
Pitfalls
-
Don't mix promises and effects—wrap with Effect.try/tryPromise
-
Don't return raw values inside Effect.gen —always yield* an Effect
-
Unsatisfied R requirements → provide layers or adjust architecture
Local Source Reference
CRITICAL: Search local Effect source before implementing
The full Effect source code is available at docs/effect-source/ . Always search the actual implementation before writing Effect code.
Key Source Files
-
Core Effect: docs/effect-source/effect/src/Effect.ts
-
Layer: docs/effect-source/effect/src/Layer.ts
-
Data: docs/effect-source/effect/src/Data.ts
-
Match: docs/effect-source/effect/src/Match.ts
Example Searches
Find Effect.gen implementation and patterns
grep -rF "Effect.gen" docs/effect-source/effect/src/
Find all map/flatMap/andThen variants
grep -rF "export" docs/effect-source/effect/src/Effect.ts | grep -F "map" grep -rF "export" docs/effect-source/effect/src/Effect.ts | grep -F "flatMap" grep -rF "export" docs/effect-source/effect/src/Effect.ts | grep -F "andThen"
Study error handling patterns
grep -rF "catchTag" docs/effect-source/effect/src/ grep -rF "catchAll" docs/effect-source/effect/src/ grep -rF "TaggedError" docs/effect-source/effect/src/
Find Effect.all concurrency patterns
grep -rF "Effect.all" docs/effect-source/effect/src/
Workflow
-
Identify the API you need (e.g., Effect.gen, Effect.all)
-
Search docs/effect-source/effect/src/Effect.ts for the implementation
-
Study the types, overloads, and patterns
-
Look at test files in docs/effect-source/effect/test/ for usage examples
-
Write your code based on real implementations
Real source code > documentation > assumptions
References
-
Agent Skills overview: https://www.anthropic.com/news/skills
-
Skills guide: https://docs.claude.com/en/docs/claude-code/skills
-
EffectPatterns: https://github.com/PaulJPhilp/EffectPatterns