fix(spec): gen:docs 给「元素是联合类型」的数组补上括号 —— (string | number)[],不再是 string | number[] (#5338) - #5793
Merged
Merged
Conversation
…cells (#5338) `format-type.ts` appended `[]` straight onto the rendered element, and `[]` binds tighter than `|` — so an array of `string | number` printed as `string | number[]`, which states "a string, OR an array of numbers". The cell and the schema were different types, on the one line metadata authors copy. Widen #4912's depth scan from `&` to `& | |`: the two operators share one rule (`[]` is not distributive over either), so `hasTopLevelIntersection` becomes `hasTopLevelUnionOrIntersection`. Nested operators inside `{}` / `<>` / `[]` / `()` are still ignored, so `Enum<'a' | 'b'>[]` and `Record<string, string | number>[]` gain no stray brackets. Regenerated `content/docs/references/**`: 19 pages, 42 cells, 47 brackets added; no page created, resurrected or deleted; `check:docs` reports all 240 generated files in sync. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
baozhoutao
marked this pull request as ready for review
August 6, 2026 06:02
This was referenced Aug 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5338
前提复核(先于实现,针对
origin/main@1624f4a)立案时的判断全部成立,没有过期:
packages/spec/scripts/lib/format-type.ts存在,gen:docs 把数组内的 passthrough 对象渲染成Record<string, any>[],抹掉已声明键 —— #4001 战役每个 open 分类站点都会复发 #4912(合入为 PR fix(spec): gen:docs 保留 passthrough 对象的已声明键 + 开放性标记,不再塌缩成 Record (#4912) #5339)引入的hasTopLevelIntersection()与指向本单的注释都在原处;[]」,对顶层联合不加括号;content/docs/references/ui/action.mdx:136印的是Record< string, { description?: string; enum?: string | number[]; examples?: any[] } >。缺陷本身
TypeScript 里
[]的结合优先级高于|,和高于&是同一回事:string或numberstring | number[]string或{ id, label, default }string | { id: string; … }[]单元格声明的类型和 schema 声明的不是同一个。参考页的类型单元格正是元数据作者
(尤其是 AI 作者)直接照抄的那一行:照着
string | number[]写下一个裸 string,schema 会当场拒绝,而页面看起来是允许的——这正是 #4001 战役在追的「声明与呈现不符」。
修法
按立案建议,只有一处:
hasTopLevelIntersection放宽为hasTopLevelUnionOrIntersection,深度扫描同时识别顶层&与|。两者本来就是同一条规则——
[]对这两个运算符都不满足分配律(A & B[]是A & (B[]),A | B[]是A | (B[]))——所以共用一次扫描,而不是并列两个函数。#4912 当时把扫描限定在
&,是因为交叉类型元素是那个 PR 自己引入的,而联合侧是既有缺陷、重生成 diff 会把真正的 passthrough 修复埋掉;那条注释现在改写成了两半合一的说明。
深度扫描原本就正确忽略
{}/< >/[]/()内部的运算符,所以Enum<'a' | 'b'>[]、Record< string, string | number >[]、{ k?: string | number }[]和 markdown 链接都保持原样,不会多出括号。重生成结果与规模
pnpm --filter @objectstack/spec gen:docs(输入是本分支合入树里的当前 schema):git status只有 modified,没有新增页,也没有被删除的页被复活;pnpm --filter @objectstack/spec check:docs报告240 generated files in sync(不动点)。关于规模与立案里「164 处」的差异,这里如实说明,不硬凑:立案的 164 是对整个
json-schema/语料(1608 个文件)按节点扫描得到的原始站点数,同一个共享 shape在每个引用它的 schema 的
$defs里都被数一次;而参考页对每个 shape 只渲染一次,或者干脆渲染成
$ref链接。我在本分支上复测:原始站点数 415(联合 356 + 交叉 59),去重后只有 22 个不同的单元格字符串,落到页面上就是 42 行 / 47 处。修复后再跑同一
探针:渲染成未加括号的站点为 0。也就是说覆盖是完全的,只是「站点」和「单元格」
是两个不同的口径。
样例(
content/docs/references/automation/state-machine.mdx,|是 GFM 单元格转义):测试
packages/spec/scripts/format-type.test.ts新增 7 个用例(该文件共 19 个,全绿),覆盖:基本类型联合、对象变体联合(取真实的
AiModelsResponse.models节点)、JSON Schema 的
type: [a, b]数组写法、联合里嵌数组变体(取真实的View.list.filter[].value,外层联合不加括号、内层数组加)、嵌套数组每层各加一次、联合里混有交叉变体,以及一组「不该加括号」的反向用例。
反向验证(方向事先判定,结果如实记录)。 把扫描收窄回
&(即本 PR 之前的hasTopLevelIntersection)重跑:方向是最常见的那一种(还原缺陷 → 新 pin 变红),因为这些用例断言的是修复产出的正形状。
但新块 7 个用例里只红了 5 个,这一点写进了测试文件的注释而不是含糊带过:
「联合里混有交叉变体」那条本来就被
&那一半括起来了(它两个运算符都有),「不该加括号」那条断言的是括号不出现——两条都是诚实的非回归用例,不是死 pin。
#4912 的交叉侧 pin 全部保持绿,
({ label: string; value: … } & Record< string, any >)[]行为不变。
其余验证:
pnpm --filter @objectstack/spec test→319 passed (319)/8151 passed (8151)pnpm --filter @objectstack/spec typecheck→tsc --noEmit通过 +check:test-typecheck: OKnode scripts/check-nul-bytes.mjs→ OK(5678 个受跟踪文本文件,无裸控制字节)Changeset
包含
.changeset/format-type-union-array-brackets.md(@objectstack/specpatch)——本 PR 改的是读者可见的生成参考文档,因此走 changeset 而不是
skip-changeset。已知陷阱处理
#5358:任何 spec build/gen 都会顺手改写
packages/spec/authorable-surface.base.json。本 PR 提交前逐文件核对并
git checkout --还原了该文件,git show --stat HEAD确认它不在本次提交里。
关联:#4912 / PR #5339(同一渲染器,交叉类型侧)、#4001(战役)。
🤖 Generated with Claude Code
https://claude.ai/code/session_01559M8FVm6W6vDLABL3jvdW
Generated by Claude Code