Error Channels and Dependencies
Track typed errors and injected dependencies in effects.
Error Channels and Dependencies is a free TypeScript Academy lesson on CoddyKit — lesson 4 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.
Error Channels and Dependencies
Two channels make Effect powerful: the typed error channel (E) and the requirements channel (R). This lesson shows how to fail with typed errors and how to provide dependencies via Context and Layer.
Typed Failures With Effect.fail
Effect.fail places a value into the error channel. Tagged classes make errors easy to discriminate.
import { Effect } from "effect";
class NotFound { readonly _tag = "NotFound"; }
class Forbidden { readonly _tag = "Forbidden"; }
const load = Effect.fail(new NotFound());
// Effect<never, NotFound, never>Errors Union as You Compose
Sequencing effects with different errors unions them in the E channel, so the type lists every failure mode.
// Effect<A, NotFound, never> then Effect<B, Forbidden, never>
// => Effect<B, NotFound | Forbidden, never>Handling Errors
Effect.catchAll or catchTag handle errors, removing them from the channel (or replacing them). Handling NotFound narrows E.
import { Effect, pipe } from "effect";
const safe = pipe(
Effect.fail(new NotFound()),
Effect.catchTag("NotFound", () => Effect.succeed("default"))
);
// Effect<string, never, never> -- error handledRecovering vs Propagating
If you do not handle an error, it stays in E and propagates to the caller, who must then handle or re-propagate it. The compiler ensures errors are never silently lost.
Declaring a Dependency
A service is declared as a Context.Tag. Effects that use it gain the service in their R channel.
import { Context, Effect } from "effect";
class Random extends Context.Tag("Random")<
Random,
{ readonly next: Effect.Effect<number> }
>() {}
const program = Effect.gen(function* () {
const random = yield* Random;
return yield* random.next;
});
// Effect<number, never, Random>Requirements Show in the Type
Notice the R channel now contains Random. The effect cannot run until that requirement is satisfied; the compiler enforces it.
Providing With a Layer
A Layer describes how to build a service. Providing a layer satisfies the requirement and clears it from R.
import { Effect, Layer } from "effect";
const RandomLive = Layer.succeed(Random, {
next: Effect.sync(() => Math.random()),
});
const runnable = Effect.provide(program, RandomLive);
// Effect<number, never, never> -- R clearedLayers Compose
Layers can depend on other layers and merge together, building a full dependency graph. Effect wires them in the correct order based on their types.
import { Layer } from "effect";
// Layer.merge(DatabaseLive, LoggerLive)
// Layer that provides both servicesTesting by Swapping Layers
Because dependencies are explicit, tests provide a different layer (e.g. a deterministic Random) without touching the program under test, a major benefit of requirement tracking.
import { Layer, Effect } from "effect";
const RandomTest = Layer.succeed(Random, {
next: Effect.succeed(0.5),
});
// Effect.provide(program, RandomTest) -> deterministicWhy This Matters
The error and requirements channels turn invisible assumptions into compiler-checked contracts: every failure must be handled or declared, and every dependency must be provided. This is what makes large Effect programs robust and testable.
Quick Check
Confirm your understanding of error channels and dependencies.
Recap
The error channel tracks typed failures (Effect.fail, narrowed by catchTag/catchAll) that union as you compose, while the requirements channel tracks services declared via Context.Tag and satisfied by Layers through Effect.provide. Together they make failures and dependencies compiler-checked and tests easy via layer swapping.
Frequently asked questions
Is the “Error Channels and Dependencies” lesson free?
Yes — the full text of “Error Channels and Dependencies” 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 “Error Channels and Dependencies”?
Track typed errors and injected dependencies in effects. 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 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Error Channels and Dependencies” 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
- Why Effect Systems Matter
- The Effect Type
- Composing Effects
- Error Channels and Dependencies