Effect 是一个偏函数式(FP)的 TypeScript 框架,类似 Scala 生态的 ZIO,核心目标是用类型系统统一管理:副作用、错误处理、依赖注入和并发控制。
核心类型:Effect<A, Error, R>
Effect.Effect<User, NotFoundError, Database>
三个泛型参数分别是:
A— 成功时的返回值类型Error— 可能抛出的错误类型(编译期已知)R— 运行时需要注入的依赖环境
相比普通 async/await,错误类型不再是 unknown,依赖关系从运行时隐式变为类型系统显式。
四个核心能力
类型安全的错误处理
// 传统方式:不知道会抛什么
try {
await fetchUser(id);
} catch (e) { }
// Effect 方式:错误类型在签名里
const fetchUser = (id: string): Effect.Effect<User, NotFoundError | DbError, Database> =>
Effect.gen(function* () {
const db = yield* Database;
return yield* db.findUser(id);
});
依赖注入
const Database = Context.Tag<Database>("Database");
// 运行时注入具体实现
Effect.runPromise(
program.pipe(
Effect.provide(DatabaseLive)
)
);
并发控制
// 限制并发数为 5
await Effect.runPromise(
Effect.all(tasks, { concurrency: 5 })
);
内置 fiber(轻量协程)、timeout、retry、race、cancellation,都是一等公民。
Resource 管理(自动释放)
const withDb = Effect.acquireRelease(
Effect.sync(() => new DbConnection()),
(conn) => Effect.sync(() => conn.close())
);
不用手写 try/finally,连接/文件/WebSocket 用完自动关闭。
基础用法示例
import { Effect, pipe } from "effect";
const program = pipe(
Effect.succeed(1),
Effect.map(n => n + 1),
Effect.flatMap(n => Effect.succeed(n * 2))
);
Effect.runPromise(program).then(console.log); // 4
Generator 风格(更接近 async/await):
const program = Effect.gen(function* () {
const a = yield* Effect.succeed(1);
const b = yield* Effect.succeed(a + 1);
return b * 2;
});
与其他框架对比
| 框架 | 风格 | 适合场景 |
|---|---|---|
| Express / Hono | 极简 | 快速 API |
| NestJS | OOP + DI | 企业级 Web |
| RxJS | 响应式流 | 事件流处理 |
| Effect | FP + 类型系统 | 复杂异步系统 |
适合的场景
Effect 的学习曲线较陡(大量 pipe、flatMap、generator),不适合小型项目。适合:
- 大型 Node.js 后端服务
- AI Agent / 工作流调度系统
- 微服务(高并发 + 复杂错误处理)
- CLI 框架
- 爬虫调度
核心标准:“复杂异步 + 大量错误路径”——这正是 Effect 最能体现价值的地方。如果只是 await fetch(),用 Promise 就够了。
