资讯动态

Effect Schema JSON Schema 输出优化:同类型字面量联合分支折叠为单一 enum 数组

发布时间:2026/9/14 8:03:22 来源:尧图企业网站定制
Effect Schema JSON Schema 输出优化同类型字面量联合分支折叠为单一 enum 数组【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effectEffect 的 Schema 模块负责将类型安全的 Schema 定义编译为 JSON Schema广泛用于 HTTP API 规范、OpenAPI 文档、MCP 工具描述与 AI 结构化输出等场景。本文基于当前仓库中待发布的变更集 compact-json-schema-enum.md讲解本次针对effect包的 patch 级优化把 JSON Schema 输出中「同类型字面量分支」从冗长的anyOf单值枚举结构折叠为一个带enum数组的紧凑对象并深入源码说明折叠的触发条件、边界限制与测试验证方式。读完本文你能掌握该优化的具体行为、从源码定位实现与测试的方法以及它在实际 JSON Schema 生成链路中的影响。变更内容从 anyOf 单值枚举到单一 enum 数组该变更集是一个标准的 changeset 文件YAML frontmatter 标明作用于effect包且版本 bump 级别为patch正文描述的优化为Schema: collapse same-type literal branches in JSON Schema output into a singleenumarray, closes #1868.即当多个同类型的字面量分支出现在 JSON Schema 输出中时将它们合并为一个enum数组。变更集给出的前后对照示例非常直观优化前{ anyOf: [ { type: string, enum: [A] }, { type: string, enum: [B] } ] }优化后{ type: string, enum: [A, B] }两者在 JSON Schema 语义上完全等价前者表示「是只允许 A 的字符串或只允许 B 的字符串」后者直接表示「是取值为 A 或 B 的字符串」。但后者的表达更紧凑、更接近手写 JSON Schema 的惯例也更容易被各类校验器、文档工具与语言模型解析。实现位置toJsonSchemaDocument 中的 Union 分支处理折叠逻辑位于 Effect 核心包的 JSON Schema 编译器内部实现 toJsonSchemaDocument.ts。该文件负责把SchemaRepresentation.DocumentEffect 内部的规范表示层逐节点递归编译为 draft-2020-12 的 JSON Schema 对象。折叠入口Union 编译路径在递归函数处理Union表示节点的分支中见 toJsonSchemaDocument.ts#L521-L530逻辑为先递归编译联合类型的每个成员types当成员数大于 1、且联合模式为默认的anyOf时调用compactEnums(types)尝试折叠若compactEnums返回undefined即不满足折叠条件则回退为原有的{ anyOf: types }或按模式输出{ oneOf: types }结构。这意味着折叠只作用于anyOf语义的联合以oneOf模式编译的联合类型不会触发该优化因为oneOf要求「恰好匹配一个分支」而合并后的enum表达与anyOf语义一致与oneOf的排他性语义不能简单互换。折叠判定compactEnums 的三重安全检查compactEnums函数见 toJsonSchemaDocument.ts#L590-L608是整个优化的核心它遍历所有候选分支只有在同时满足以下条件时才返回折叠结果{ type: sharedType, enum: values }任一条件不满足即返回undefined放弃折叠分支结构纯净每个分支对象的键必须恰好是type与enum两个keys.length ! 2则放弃。也就是说只要某个分支带有title、description、pattern等附加关键字就不具备折叠条件——否则合并会丢失这些成员级标注类型一致所有分支的type必须相同首个分支确定sharedType后续分支与之比对不一致则放弃。这正是变更集标题中「same-type」的含义取值无重复各分支enum中的值在合并后不得重复values.includes(value)命中则放弃。同时要求每个分支的enum数组非空。全部检查通过时函数将所有分支的枚举值按原顺序拼接为一个数组输出{ type: sharedType, enum: values }。从源码结构看该判定是保守的宁可输出略冗长的anyOf也不产生语义偏移或信息丢失。折叠的上游来源字面量分支如何产生被折叠的「单值 enum 分支」是 Effect 把字面量 Schema 编译为 JSON Schema 的自然结果。同一文件中Literal节点的编译规则见 toJsonSchemaDocument.ts#L366-L367为符号字面量编译为{ type: string, enum: [String(literal)] }其他字面量字符串、数字、布尔、null编译为{ type: typeof literal, enum: [literal] }。因此当你定义形如Schema.Union(Schema.Literal(A), Schema.Literal(B))的 Schema对应 TypeScript 类型A | B并以anyOf模式输出时每个成员各自产出{ type: string, enum: [A] }与{ type: string, enum: [B] }恰好命中折叠条件最终输出即变更集中展示的{ type: string, enum: [A, B] }。测试验证折叠与不折叠的边界用例仓库为这一行为提供了直接对应的测试用例位于 toJsonSchemaDocument.test.ts#L299-L331在unions描述块中定义了正反两条边界用例一同类型字面量联合应被折叠compacts a union of same-type literals——两个Literal节点a、b以anyOf模式组成Union断言编译结果严格等于{ type: string, enum: [a, b] }与变更集的 After 示例一一对应。用例二混合类型字面量联合不应折叠does not compact a union of mixed-type literals——astring与1number组成的Union因type不一致而不满足折叠条件断言结果保持原有结构{ anyOf: [ { type: string, enum: [a] }, { type: number, enum: [1] } ] }这两条用例恰好覆盖了compactEnums中「类型一致」判定的正反两面也为维护者提供了回归依据任何改动若使混合类型联合被错误折叠或使同类型联合不再折叠都会在 packages/effect/test/schema/representation/ 下的测试中暴露。影响范围与适用边界从当前仓库的源码结构看toJsonSchemaDocument是 Effect 中 JSON Schema 生成的公共下游Schema.ts 的对外 API 经由表示层SchemaRepresentation.ts与 JSON Schema 文档编译链路工作而 AI 工具参数 Schema、HTTP API 的 OpenAPI 生成等模块如 structured-output.ts、OpenApi.ts均会经过这条链路。因此本次折叠带来的收益是凡是输出「同类型字面量联合」的 Schema其 JSON Schema 产物都会变得更紧凑、更贴近人类手写习惯同时保持语义完全等价。使用与评估时需注意以下边界均与源码判定一致仅 anyOf 模式oneOf模式的联合类型不会触发折叠仅纯单值枚举分支任何携带额外关键字如title、description的分支都会使折叠整体放弃类型必须严格相同string 与 number 等混合类型联合维持原anyOf结构输出枚举值不得重复合并后出现重复取值时同样回退。另外该变更集当前位于 .changeset/pre/ 目录属于待随effect包下一个补丁版本发布的变更frontmatter 中标注effect: patch其描述的优化已在本仓库源码与测试中就位。小结本次 compact-json-schema-enum.md 描述的优化是 Effect Schema 在 JSON Schema 生成链路上的一处低侵入、高收益的规范化改进通过 compactEnums 在Union编译路径上安全折叠同类型单值枚举分支将anyOf: [{ type: string, enum: [A] }, { type: string, enum: [B] }]精简为{ type: string, enum: [A, B] }。整个过程以保守判定换取零语义变更并由 toJsonSchemaDocument.test.ts 中的正反用例固化行为边界是阅读 Effect「类型 Schema → 标准 JSON Schema」编译链路的一个很好的切入点。【免费下载链接】effectBuild production-ready applications in TypeScript项目地址: https://gitcode.com/GitHub_Trending/ef/effect创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价