关于 effect-ts
面向编写或审查 Effect TypeScript 代码的开发者,按领域整理参考指南,涵盖核心概念、错误处理、并发、平台 API 和迁移。
主要功能
- 01按领域组织的 Effect 参考指南
- 02类型化错误与恢复模式
- 03服务、层与资源安全
- 04Schema 验证与转换
- 05并发、流与调度
- 06相关库的迁移指南
适用场景
- 01审查使用 Effect 的代码
- 02使用依赖注入设计服务
- 03用 Schema 验证和转换数据
- 04将基于 Promise 的代码迁移到 Effect
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill effect-ts安装后在 Claude Code 中输入/effect-ts确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
gotchas.mdmetadata.jsonreferences/_sections.mdai-integration.mdcode-style.mdconc-concurrency.mdcore-concepts.mddata-types.mderror-management.mdgetting-paradigm.mdgetting-started.mdmicro-module.mdmigration-guides.mdobs-observability.mdplat-platform.mdreq-management.mdresource-management.mdsched-scheduling.mdschema-advanced.mdschema-basics.mdstate-management.mdstreams-and-sinks.mdtest-testing.md详细介绍
Effect TypeScript 最佳实践
Effect 是一个 TypeScript 库,用于构建复杂且类型安全的应用,提供结构化错误处理、通过服务/层实现的依赖注入、基于 fiber 的并发处理和资源安全。
适用场景
- 编写或审查从
effect、@effect/schema或@effect/platform导入内容的 TypeScript 代码 - 使用
Effect<Success, Error, Requirements>实现类型化错误处理 - 构建用于依赖注入的服务和层
- 使用 Schema 进行数据验证、解码和转换
- 使用基于 fiber 的并发处理(队列、信号量、PubSub、deferred)
- 使用 Stream 和 Sink 处理数据
- 将 Promises、fp-ts、neverthrow 或 ZIO 迁移到 Effect
使用方法
本技能按领域组织。请阅读与你正在处理的领域相关的参考文件。
首先阅读:范式
在深入阅读 API 参考之前,务必先阅读此内容,尤其是在重构现有代码以使用 Effect 或编写新的 Effect 服务时:
| 参考资料 | 阅读时机 |
|---|---|
| 以 Effect 的方式思考:范式转变 | 阅读任何其他参考资料之前。 思维模型转变、重构方案、反模式和应用架构。请阅读此内容,了解如何以 Effect 的方式思考——其他文件会教你要编写什么。 |
核心基础
| 参考资料 | 阅读时机 |
|---|---|
| 入门 | 创建 Effect 类型、管道、生成器、运行 Effect |
| 错误管理 | 类型化错误、恢复、重试、超时、沙箱 |
| 核心概念 | 请求批处理、配置管理、运行时系统 |
数据与验证
| 参考资料 | 阅读时机 |
|---|---|
| 数据类型 | Option、Either、Cause、Chunk、DateTime、Duration、Exit、Data |
| Schema 基础 | Schema 简介、基本用法、类、构造函数、Effect 数据类型 |
| Schema 进阶 | 转换、过滤器、注解、错误格式化、JSON Schema 输出 |
架构与依赖
| 参考资料 | 阅读时机 |
|---|---|
| 依赖需求管理 | 服务、层、依赖注入、层记忆化 |
| 资源管理 | Scope、安全地获取/释放资源、缓存 |
| 状态管理 | 用于并发状态的 Ref、SubscriptionRef、SynchronizedRef |
并发与流处理
| 参考资料 | 阅读时机 |
|---|---|
| 并发 | Fibers、Deferred、Latch、PubSub、Queue、Semaphore |
| 流与 Sink | 创建、消费、转换流;Sink 操作 |
| 调度 | 内置调度、cron、组合器、重复执行 |
平台与可观测性
| 参考资料 | 阅读时机 |
|---|---|
| 平台 | FileSystem、Command、Terminal、KeyValueStore、Path |
| 可观测性 | 日志、指标、追踪、Supervisor |
| 测试 | 用于时间模拟的 TestClock;有关服务模拟和层测试,请参阅依赖需求管理 |
样式、AI 与迁移
| 参考 | 阅读时机 |
|---|---|
| 代码风格 | 品牌类型、模式匹配、双 API、指南、特征 |
| AI 集成 | 用于 LLM 工具调用和执行规划的 Effect AI 包 |
| Micro | 适用于较小打包体积的轻量级 Effect 替代方案 |
| 迁移指南 | 从 Promises、fp-ts、neverthrow 或 ZIO 迁移时 |
快速参考 — 常见模式
Effect 类型
// ┌─── Success type
// │ ┌─── Error type
// │ │ ┌─── Required dependencies
// ▼ ▼ ▼
Effect<Success, Error, Requirements>
创建 Effect
import { Effect } from "effect"
// From sync values
const succeed = Effect.succeed(42)
const fail = Effect.fail(new Error("oops"))
// From sync code that may throw
const sync = Effect.try(() => JSON.parse(data))
// From promises
const async = Effect.tryPromise(() => fetch(url))
// From generators (recommended for complex flows)
const program = Effect.gen(function* () {
const user = yield* getUser(id)
const todos = yield* getTodos(user.id)
return { user, todos }
})
运行 Effect
// Async (returns Promise)
Effect.runPromise(program)
// With full Exit information
Effect.runPromiseExit(program)
// Sync (throws on async)
Effect.runSync(program)
类型化错误
import { Data, Effect } from "effect"
class NotFound extends Data.TaggedError("NotFound")<{
readonly id: string
}> {}
class Unauthorized extends Data.TaggedError("Unauthorized")<{}> {}
// Error type is tracked: Effect<User, NotFound | Unauthorized>
const getUser = (id: string) =>
Effect.gen(function* () {
// ...
})
服务与层
import { Context, Effect, Layer } from "effect"
// Define a service
class UserRepo extends Context.Tag("UserRepo")<
UserRepo,
{ readonly findById: (id: string) => Effect.Effect<User, NotFound> }
>() {}
// Use in effects — adds to Requirements channel
const program = Effect.gen(function* () {
const repo = yield* UserRepo
return yield* repo.findById("1")
})
// Implement with a Layer
const UserRepoLive = Layer.succeed(UserRepo, {
findById: (id) => Effect.succeed({ id, name: "Alice" })
})
// Provide and run
program.pipe(Effect.provide(UserRepoLive), Effect.runPromise)
Schema 验证
import { Schema } from "effect"
const User = Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.String.pipe(Schema.pattern(/@/))
})
type User = typeof User.Type
// Decode (parse + validate)
const decode = Schema.decodeUnknownSync(User)
const user = decode({ id: 1, name: "Alice", email: "[email protected]" })
管道
import { Effect, pipe } from "effect"
// Data-last (pipe style)
const result = pipe(
getTodos,
Effect.map((todos) => todos.filter((t) => !t.done)),
Effect.flatMap((active) => sendNotification(active.length)),
Effect.catchTag("NetworkError", () => Effect.succeed("offline"))
)
// Fluent (method style)
const result2 = getTodos.pipe(
Effect.map((todos) => todos.filter((t) => !t.done)),
Effect.flatMap((active) => sendNotification(active.length))
)
易错点
已知的失败点请参阅 gotchas.md。
评论
支持 Markdown