mcpField
E
effect-ts-anti-patterns

effect-ts-anti-patterns

github.com/mrevanzak测试与质量896 次安装39 周前更新
代码仓库

关于 effect-ts-anti-patterns

一份 Effect-TS 代码审查与调试参考,帮助识别可能导致资源泄漏、崩溃或未处理错误的常见误用,面向使用 Effect-TS 的开发者,不适用于普通 TypeScript 或其他函数式库。

主要功能

  1. 01说明常见 Effect-TS 反模式
  2. 02展示更安全的 Effect 组合
  3. 03涵盖类型化错误处理
  4. 04指导限制并发
  5. 05介绍可安全中断的资源清理
  6. 06列出代码审查警示项

适用场景

  1. 01审查 Effect-TS 代码
  2. 02排查未处理的 Promise 拒绝
  3. 03避免过量并发任务
  4. 04检查资源清理与错误处理路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mrevanzak/effect-ts-skills --skill effect-ts-anti-patterns

安装后在 Claude Code 中输入/effect-ts-anti-patterns确认已加载。

详细介绍

Effect-TS 反模式

概述

Effect-TS 提供了强大的函数式框架,但常见的命令式习惯可能绕过其安全保障。本技能会识别并修复导致资源泄漏、进程崩溃和未处理错误的模式。

适用场景

  • 在审查 Effect-TS 实现的代码时。
  • 在调试 Effect 代码中的“未处理的 Promise 拒绝”或进程崩溃时。
  • 在优化并行操作的性能时。

不适用场景:

  • 对于简单的非 Effect TypeScript 代码。
  • 使用其他函数式库(如 fp-ts 等)时。

反模式参考

反模式错误代码正确代码原因
在边界之外运行函数中途执行 await Effect.runPromise(fx)yield* fx(组合)绕过错误通道和追踪。
缺少 yield*const user = yield fetchUser()const user = yield* fetchUser()生成的是 Effect 对象,而不是结果。
抛出错误if (!ok) throw new Error()yield* Effect.fail(new Error())throw 会创建“缺陷”(导致崩溃),而不是类型化错误。
无界并行Effect.all(tasks)(默认)Effect.all(tasks, { concurrency: 10 })防止内存溢出和速率限制耗尽。
忽略错误Effect.runPromise(fx)(无捕获)fx.pipe(Effect.catchAll(...))会导致未处理的拒绝。
手动清理try { ... } finally { cleanup() }Effect.acquireRelease(...)finally 无法保证在中断时执行清理。

常见错误

1. yield 与 yield* 的陷阱
// ❌ BAD: Missing *, yields the Effect object itself
const bad = Effect.gen(function* () {
  const user = yield fetchUser(id); // Returns Effect, not User!
});

// ✅ GOOD: yield* executes the Effect
const good = Effect.gen(function* () {
  const user = yield* fetchUser(id); // Returns User
});
2. 无界并行
// ❌ BAD: 10,000 concurrent requests (OOM risk)
const bad = Effect.all(urls.map(fetch));

// ✅ GOOD: Bounded to 10 concurrent
const good = Effect.all(urls.map(fetch), { concurrency: 10 });
3. 在代码中途运行 Effect
// ❌ BAD: Effect.runPromise scattered throughout
const bad = async () => {
  const user = await Effect.runPromise(getUser(id));
  const posts = await Effect.runPromise(getPosts(user.id));
};

// ✅ GOOD: Compose effects, run ONCE at boundary
const good = Effect.gen(function* () {
  const user = yield* getUser(id);
  const posts = yield* getPosts(user.id);
  return { user, posts };
});

合理化说辞对照表

借口事实
“我会用 concurrency: 'unbounded' 来提速”快 = 崩溃。处理外部资源时始终要限制并行度。
“我先直接 throw 吧”throw 会绕过错误通道,使代码无法测试。
“在这里运行更简单”在代码中途运行会丢失上下文和追踪,也无法确保中断安全。

危险信号

  • 在循环或辅助函数中使用 Effect.runPromise 或 Effect.runSync。
  • 对大型列表使用 Effect.all 时未设置 concurrency 选项。
  • 在 Effect.gen 代码块中使用 throw 关键字。
  • 调用 Effect 时使用 yield 而不加 *。

交叉引用

  • 必备背景知识: effect-ts-fundamentals
  • 必备子技能: effect-ts-concurrency
  • 参考: effect-ts-resources

评论

支持 Markdown