TypeScript Academy · 课时

错误通道与依赖

跟踪效果中的带类型错误和注入依赖。

第 4 / 4 课13 个步骤

错误通道与依赖 是 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 效果系统为何重要
  2. Effect 类型
  3. 组合效果
  4. 错误通道与依赖
← 返回 TypeScript Academy