错误通道与依赖
跟踪效果中的带类型错误和注入依赖。
错误通道与依赖 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。
错误通道与依赖项
两个通道让 Effect 变得强大:带类型的错误通道(E)和需求通道(R)。本课将展示如何使用带类型的错误使操作失败,以及如何通过 Context 和 Layer 提供依赖项。
使用 Effect.fail 产生带类型的失败
Effect.fail 会将一个值放入错误通道。带标签的类让错误更容易区分。
import { Effect } from "effect";
class NotFound { readonly _tag = "NotFound"; }
class Forbidden { readonly _tag = "Forbidden"; }
const load = Effect.fail(new NotFound());
// Effect<never, NotFound, never>组合时错误会合并为联合类型
依次执行具有不同错误类型的效果时,这些错误会在 E 通道中合并为联合类型,因此该类型会列出所有失败情况。
// Effect<A, NotFound, never> then Effect<B, Forbidden, never>
// => Effect<B, NotFound | Forbidden, never>处理错误
Effect.catchAll 或 catchTag 可以处理错误,将错误从通道中移除(或替换为其他错误)。处理 NotFound 会缩小 E 的类型范围。
import { Effect, pipe } from "effect";
const safe = pipe(
Effect.fail(new NotFound()),
Effect.catchTag("NotFound", () => Effect.succeed("default"))
);
// Effect<string, never, never> -- error handled恢复与传播
如果您不处理错误,它就会留在 E 中并传播给调用方,而调用方必须处理它或继续传播它。编译器会确保错误不会被悄悄丢弃。
声明依赖项
服务会声明为 Context.Tag。使用该服务的效果会在其 R 通道中获得这项服务。
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>需求会显示在类型中
请注意,R 通道现在包含 Random。在满足该需求之前,这个效果无法运行;编译器会强制执行这一点。
使用 Layer 提供依赖项
Layer 描述如何构建一项服务。提供一个层即可满足需求,并将其从 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 cleared层可以组合
层可以依赖其他层并相互合并,从而构建完整的依赖关系图。Effect 会根据类型按正确顺序连接它们。
import { Layer } from "effect";
// Layer.merge(DatabaseLive, LoggerLive)
// Layer that provides both services通过替换层进行测试
由于依赖项是显式声明的,测试可以提供一个不同的层(例如确定性的 Random),而无需改动被测试的程序,这是需求跟踪带来的重要优势。
import { Layer, Effect } from "effect";
const RandomTest = Layer.succeed(Random, {
next: Effect.succeed(0.5),
});
// Effect.provide(program, RandomTest) -> deterministic为什么这很重要
错误通道和需求通道将隐含的假设转化为由编译器检查的契约:每个失败都必须被处理或声明,每个依赖项都必须被提供。这正是大型 Effect 程序可靠且易于测试的原因。
快速检查
确认您对错误通道和依赖项的理解。
回顾
错误通道跟踪带类型的失败(Effect.fail,由 catchTag/catchAll 缩小范围),这些失败在组合时会合并为联合类型;而需求通道跟踪通过 Context.Tag 声明、并通过 Layer 和 Effect.provide 满足的服务。两者结合后,失败和依赖项都由编译器检查,并且通过替换层可以轻松进行测试。
用 AI 导师学习 TypeScript — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 101
- 课程
- 352
常见问题解答
「错误通道与依赖」课时是免费的吗?
是的 — 「错误通道与依赖」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。
「错误通道与依赖」这节课中我会学到什么?
跟踪效果中的带类型错误和注入依赖。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 TypeScript Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「错误通道与依赖」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 TypeScript Academy 课中编写并运行代码吗?
能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。