effect-smol Schema中间件完全指南:5个快速拦截编解码的高级技巧
【免费下载链接】effect-smolCore libraries and experimental work for Effect v4项目地址: https://gitcode.com/GitHub_Trending/ef/effect-smol
effect-smol 是 Effect v4 的核心库仓库,其 Schema 模块提供了强大的Schema中间件机制:你可以在不修改原有校验逻辑的前提下,拦截(intercept)解码和编码流水线,实现失败兜底、动态注入服务、日志观测等高级能力。本文带你用 5 个实用技巧快速上手。
为什么需要 Schema 中间件:拦截编解码的本质
普通校验只能"通过或不通过",而**中间件(Middleware)**包裹在编解码过程之外,让你可以:
- 🛡️拦截错误:捕获解码失败(Issue),改成兜底值或换一种失败方式
- 🧩注入服务:让兜底逻辑依赖外部服务(如从配置中心读取默认值)
- 📝观测过程:记录编解码失败日志,不改业务代码
Schema 中间件的 4 个核心 API 一览:
| API | 作用方向 | 适合场景 |
|---|---|---|
Schema.middlewareDecoding | 解码 | 拦截整个解码流水线,可注入服务 |
Schema.middlewareEncoding | 编码 | 拦截整个编码流水线 |
Schema.catchDecoding | 解码 | 解码失败时返回兜底值(最简单) |
Schema.catchEncoding | 编码 | 编码失败时返回兜底值 |
💡 迁移提示:v3 中的
decodingFallback注解在 v4 已更名为catchDecoding,见 migration/schema.md 与 migration/schema.md 的详细对比。
官方文档的中间件章节位于 SCHEMA.md。
技巧一:用 middlewareDecoding 记录编解码失败日志
最简单的入门场景是"不改结果,只看失败"。middlewareDecoding会收到当前解码的Effect,你可以用Effect.tapError在失败时打日志:
const Logged = Schema.String.pipe( Schema.middlewareDecoding((effect) => Effect.tapError(effect, (issue) => Effect.log("decode failed", issue)) ) )它的完整类型签名位于 Schema.ts:传入一个函数,接收解码Effect和解析选项,返回一个新的Effect——你可以自由地添加服务依赖、恢复错误或加工结果。
技巧二:用 catchDecoding 在解码失败时自动填充默认值
解码失败兜底是中间件最常见用法。catchDecoding接收失败原因,返回一个携带兜底值的Effect:
// 解码失败时返回 "b",而不是抛错 const schema = Schema.String.pipe(Schema.catchDecoding(() => Effect.succeedSome("b"))) Schema.decodeUnknownExit(schema)(null) // Success("b")两个实用细节:
- 返回
Option.some(值)表示兜底成功;返回Option.none()表示把该字段从输出中省略,非常适合可选字段。 - 它本质上是
middlewareDecoding的快捷方式,实现见 Schema.ts。
// 可选字段解码失败时直接省略该键 const schema = Schema.Struct({ a: Schema.optionalKey(Schema.String).pipe(Schema.catchDecoding(() => Effect.succeedNone)) }) Schema.decodeUnknownExit(schema)({ a: null }) // Success({})技巧三:注入服务,让兜底值动态可得
当兜底值来自外部(配置、数据库、远程服务)时,用catchDecodingWithContext声明服务依赖,再用middlewareDecoding配合Effect.provideService注入:
class Service extends Context.Service<Service, { fallback: Effect.Effect<string> }>()("Service") {} const schema = Schema.String.pipe( Schema.catchDecodingWithContext(() => Effect.gen(function*() { const service = yield* Service return Option.some(yield* service.fallback) }) ) ) // 解码时注入服务,schema 对外部不再暴露依赖 const provided = schema.pipe( Schema.middlewareDecoding(Effect.provideService(Service, { fallback: Effect.succeed("b") })) ) Schema.decodeUnknownExit(provided)(null) // Success("b")这套"声明依赖 → 注入服务"的组合拳,让你在库代码里保持依赖声明,在调用方决定兜底策略,是 Effect 依赖注入风格在 Schema 编解码中的直接延伸。完整示例见 SCHEMA.md。
技巧四:编码方向的拦截(middlewareEncoding 与 catchEncoding)
中间件同样覆盖编码(把类型化值转回 JSON/FormData 等可序列化格式)方向:
Schema.middlewareEncoding:拦截编码流水线,可记录编码失败、注入编码所需服务,签名见 Schema.ts。Schema.catchEncoding:编码失败时返回兜底值。例如先解码成number,再编码为整数,编码失败时兜底为0:
const schema = Schema.Number.pipe( Schema.catchEncoding(() => Effect.succeed(Option.some(0))), Schema.encodeTo(Schema.Int) )解码侧和编码侧的 API 完全对称,你可以按需选择只拦截一个方向,也可以两侧都加。
技巧五:redact——防止敏感信息泄漏的内置中间件
库内置了一个典型的高级中间件:Schema.redact。它在解码失败时把错误包装进Redacted,阻止敏感的 schema 细节泄漏到错误消息中:
// 用 mapError 改写解码错误——这就是一个 middlewareDecoding export function redact(schema) { return middlewareDecoding(Effect.mapErrorEager(SchemaIssue.redact))(schema) }实现仅一行,位于 Schema.ts。它示范了如何只用一个"错误改写"函数,就构造出可复用的安全中间件。
底层原理:SchemaTransformation.Middleware 只包装"方向函数"
所有中间件最终都会变成一个SchemaTransformation.Middleware实例——它只有decode和encode两个槽位,分别存放对解码Effect和编码Effect的包装函数,类定义见 SchemaTransformation.ts。
两个设计要点值得新手理解:
- 中间件操作的是"过程"而非"值":它拿到的是整个编解码
Effect,因此可以叠加任意 Effect 组合子(catch、tapError、provideService……),表达能力远超单纯的值转换。 - 支持
flip():调用flip()可交换 decode/encode 两个方向,方便把双向中间件翻转成单视角使用。
middlewareDecoding实际上就是"给 decode 槽位填你的函数、encode 槽位保持恒等"的工厂方法。更多用法可参考官方测试中的断言示例 Schema.test.ts 与 Schema.test.ts。
总结:如何选择你的拦截方式
| 你的需求 | 推荐 API |
|---|---|
| 解码失败返回固定/静态默认值 | catchDecoding |
| 编码失败返回固定/静态默认值 | catchEncoding |
| 兜底逻辑依赖服务(配置、远程数据) | catchDecodingWithContext/catchEncodingWithContext+middlewareDecoding(Effect.provideService(...)) |
| 记录日志、改写错误、观测整个流程 | middlewareDecoding/middlewareEncoding |
| 防止错误消息泄漏敏感信息 | Schema.redact(内置中间件范例) |
掌握这 5 个技巧,你就完成了从"声明式校验"到"可编程编解码流水线"的跨越。更多 Schema 主题(基础 schema、复合结构、转换、序列化、错误格式化)可阅读 SCHEMA.md 的目录导览,仓库整体结构介绍见 LLMS.md。
【免费下载链接】effect-smolCore libraries and experimental work for Effect v4项目地址: https://gitcode.com/GitHub_Trending/ef/effect-smol
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考