Effect Schema 解码后为什么少了字段?
接口返回了 { id: 7, name: "a", role: "admin" },你用 Schema 解码后,结果里却只有 id 和 name,role 不见了。没有报错,没有警告,字段就这么消失了。
答案是:这是 Schema.Struct 的默认行为,解码时多余的字段会被剔除,输出里只留下 Schema 声明过的字段。 想保留某个字段,就在 Schema 里声明它;想让多余字段直接报错而不是悄悄丢掉,解码时传入 { onExcessProperty: "error" }。
这个默认行为是刻意的:不会让没声明的字段悄悄混进你的内部数据,对安全是友好的。Schema 是 Effect 里把运行时校验和 TypeScript 类型合成一份定义的工具,如果还不熟,先看 为什么不能相信 TypeScript 类型。下面说清楚怎么选。
想保留这个字段,怎么办?
在 Schema 里声明它。解码只会放行声明过的字段:
import { Schema } from "effect"
const User = Schema.Struct({
id: Schema.Number,
name: Schema.String,
email: Schema.optionalKey(Schema.String)
})这里 email 用 optionalKey 声明为可选。没出现在这份定义里的字段,解码后都不会出现在结果里。
想让多余字段直接报错,怎么办?
解码时传入选项 { onExcessProperty: "error" },遇到未声明的字段就失败,而不是剔除。适合你希望对方严格遵守约定、多出来的字段本身就说明有问题的场合。
失败时的类型是 SchemaError,和其他解码失败一样,带着指出「哪个字段、期望什么、实际是什么」的信息,可以在边界处翻译成你自己的领域错误,见 错误设计。
默认剔除和报错,该选哪个?
默认剔除适合大多数情况:你只关心自己声明过的字段,对方多发了什么都不会污染内部数据。选 "error" 的代价是对方一旦新增字段,你这边就会开始失败,所以只在你确实要把多余字段当成错误时再用。
本文内容沿用自我之前写的 Effect 教程章节,该章节没有标注 effect 的版本号,也没有记录运行结果,所以这里不声称在某个版本上验证过。onExcessProperty 的具体写法请对照你所用版本的文档确认。