effect-smol Schema错误处理详解:验证错误格式化与国际化完整指南
2026/9/3 14:44:52 网站建设 项目流程

effect-smol Schema错误处理详解:验证错误格式化与国际化完整指南

【免费下载链接】effect-smolCore libraries and experimental work for Effect v4项目地址: https://gitcode.com/GitHub_Trending/ef/effect-smol

effect-smol(Effect v4 核心库)中,Schema 错误处理通过结构化的Issue 错误树完成:解析失败时,错误携带字段路径、期望类型与实际值,并可按需做验证错误格式化国际化(i18n)定制。本文面向新手,带你快速掌握错误类型、格式化器与自定义提示词三件套。

为什么 Schema 的错误处理值得重视?

当你用 Schema 解析接口参数、表单数据或配置时,验证失败是常态。effect-smol 的Schema模块把失败原因封装成一棵Issue 树,而不是一个笼统的字符串,带来三个好处:

  • 精确定位:嵌套字段出问题时,错误自带路径(如["user"]["age"]
  • 可编程处理:可按错误类型分支处理,而不靠正则解析文案
  • 可定制展示:格式化器(Formatter)可替换,支持自定义文案与国际化

核心实现位于 SchemaIssue.ts 与 SchemaError.ts。

一分钟认识 Issue 错误树

每个 Issue 节点都有_tag字段标识类型,分为叶子节点组合节点两类:

节点类型含义典型场景
InvalidType类型不匹配期望字符串却收到数字
InvalidValue值不满足约束字符串长度不足、数值越界
MissingKey缺少必填字段对象漏传 key
UnexpectedKey出现多余字段严格模式下传了未知属性
Forbidden禁止的操作同步上下文中执行了异步操作
OneOf/AnyOf联合类型匹配问题无一匹配 / 多个匹配
Filter/Encoding/Pointer/Composite组合包装记录过滤失败、转换失败、路径、多错误聚合

解析失败时抛出的是SchemaError,其issue字段就是这棵错误树,message属性会自动调用默认格式化器渲染成可读文本:

try { Schema.decodeUnknownSync(Schema.Number)("not a number") } catch (err) { if (Schema.isSchemaError(err)) { console.log(err.message) // Expected number, got "not a number" } }

类型定义详见 SchemaIssue.ts。

验证错误格式化:两种开箱即用的格式化器

Issue 树本身是结构化数据,如何变成人读文案由Formatter决定。effect-smol 内置了两个:

1. 默认字符串格式化器(默认输出)

SchemaIssue.makeFormatterDefault()把错误树扁平化为多行文本,每条错误附带字段路径:

Expected string, got 42 at ["username"] Missing key at ["email"]

这也是Issue.toString()SchemaError.message的底层实现,适合日志、CLI 输出。

2. Standard Schema V1 格式化器(跨库兼容)

SchemaIssue.makeFormatterStandardSchemaV1()输出标准化的issues数组,每项包含messagepath,方便对接表单库、React Hook Form 等遵循 Standard Schema 规范的生态:

const formatter = SchemaIssue.makeFormatterStandardSchemaV1() formatter(issue) // { issues: [{ message: "Expected string, got 42", path: ["username"] }] }

两个格式化器均支持通过leafHook/checkHook回调替换具体片段的渲染逻辑,是定制文案的关键扩展点,源码见 SchemaIssue.ts。底层的值渲染(日期、循环引用、脱敏值等)由通用的 Formatter.ts 提供。

三步为错误信息做国际化(i18n)

effect-smol 没有内置语言包,但其消息机制天然支持国际化——文案是数据,不是硬编码。推荐三步走:

第一步:在 Schema 注解中写入本地化文案

通过annotateKey等注解为字段指定提示词,格式化时会优先使用注解中的message

const schema = Schema.Struct({ username: Schema.String.pipe( Schema.annotateKey({ description: "The username used to log in", messageMissingKey: "用户名不能为空" // 缺失该字段时的提示 }) ) })

注解还支持messageUnexpectedKey(多余字段)等变体,定义见 Schema.ts。

第二步:按语言选择文案源

常见做法是在 Schema 定义层注入当前语言对应的文案:

const messages = locales[lang] // 你的文案表 const UserSchema = makeUserSchema(messages.zh ?? messages.en)

第三步:用自定义 Hook 兜底未注解的错误

对没有注解的错误(如类型不匹配),提供自己的leafHook统一翻译默认模板:

const formatter = SchemaIssue.makeFormatterStandardSchemaV1({ leafHook: (issue) => { if (issue._tag === "InvalidType") { return t("schema.invalidType", { expected: "string" }) } return SchemaIssue.defaultLeafHook(issue) // 其余走默认 } })

这样,已注解字段用业务文案,未注解字段走翻译模板,即可实现完整的错误信息国际化。

敏感数据提醒

错误信息中默认包含出错的实际值(如got "abc123")。对外展示前请注意脱敏:SchemaIssue内置了redact逻辑,可将实际值替换为Redacted占位,避免密码、令牌等敏感内容进入日志或前端,相关实现见 SchemaIssue.ts。

总结与延伸阅读

需求工具
读取错误路径与原因issue树 +_tag模式匹配
人读多行文本makeFormatterDefault()
对接表单/前端生态makeFormatterStandardSchemaV1()
国际化文案annotateKey注解 + 自定义leafHook
判断是否为 Schema 错误Schema.isSchemaError(err)

更多 Schema 用法可阅读官方指南 SCHEMA.md,Schema 基础示例参考 10_schema-basics.ts,注解定义见 Schema.ts。掌握 Issue 树、格式化器与注解文案三个概念,你就已经能构建出既清晰又可国际化的验证错误处理方案了 🚀

【免费下载链接】effect-smolCore libraries and experimental work for Effect v4项目地址: https://gitcode.com/GitHub_Trending/ef/effect-smol

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询