Uh oh!
There was an error while loading. Please reload this page.
fix(types): ObjectViewSchema table/form slots ship the members they promise - #6399
Merged
Merged
Conversation
…romise Both slots were declared by deriving from the schema they document: table?: Partial<Omit<ObjectGridSchema, 'type' | 'objectName'>>; form?: Partial<Omit<ObjectFormSchema, 'type' | 'objectName' | 'mode'>>; and both derived types declared ZERO properties. `Omit<T, K>` is `Pick<T, Exclude<keyof T, K>>`, and `keyof T` on a type carrying a string index signature is `string | number` — the literal member names are absorbed. Both source schemas inherit `BaseSchema`'s `[key: string]: any` (objectui#5155), so each `Pick` rebuilt a type holding the index signature and none of the named members. Measured through the TypeScript checker: ObjectGridSchema 61 members, the Omit of it 0; ObjectFormSchema 67, the Omit of it 0. Each `Omit` is now a `Partial<Pick<…>>` over an explicit key list — 59 keys for table, 64 for form, every declared member minus the identity keys the view fixes. `Pick` with literal keys never computes `keyof T`, so it cannot collapse. The duplicate-list hazard is neutralised by a checker-driven pin that recomputes each source schema's declared members and requires set equality with the slot, so a member added to ObjectGridSchema and not to the list turns it red. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
…ectview-slot-key-lists
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
os-support-ai
marked this pull request as ready for review
August 25, 2026 20:11
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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#6269
Omit< T, K >) throughout — GitHub's bodysanitizer eats a fragment that opens with an identifier in angle brackets, which is what
mangled #6269's first revision. Source code is unaffected; this is about the prose here.
What was wrong
ObjectViewSchema's two slots were declared by deriving from the schema they document:Both derived types declared zero properties.
Omit< T, K >isPick< T, Exclude< keyof T, K > >, andkeyof Ton a type carrying a string index signatureis
string | number— the literal member names are absorbed. Both source schemas inheritBaseSchema's[key: string]: any(#5155), so eachPickrebuilt a type holding the indexsignature and none of the named members.
Measured through the TypeScript checker against the emitted declaration, on unmodified
origin/main:This is #6151's collapse in property position. Confirmed against the tree that #6151's
guard does not reach it:
packages/types/src/__tests__/stack-schema-emitted-members.test.tswalks the
LayoutSchemaunion, and these two are properties onObjectViewSchema, notunion members.
The repair — triage's option 2
Each
Omitbecame aPartialPickover an explicit key list.Pickwith literal keysnever computes
keyof T, so it cannot collapse the same way.ObjectGridSlotKey— 59 keys: everyObjectGridSchemamember minustype,objectName.ObjectFormSlotKey— 64 keys: everyObjectFormSchemamember minustype,objectName,mode.After the change, the same checker reading gives
table59 andform64 declaredproperties, every member optional (the
Partialsurvived), and no string index signatureon either slot — which is what re-enables excess-property checks.
The duplicate-list hazard, neutralised
A hand-maintained key list drifts silently the moment someone adds a member to the source
schema.
packages/types/src/__tests__/object-view-slot-key-lists.test.tsis thechecker-driven pin triage ruled: it emits the package's own declarations through the compiler
API and asserts each slot's member set equals the source schema's declared members minus
the identity keys. Same instrument that produced the 61 → 0 reading; set equality, not a spot
check.
The pin's comment records the removal condition triage asked for: these
Picklists existonly because
BaseSchemacarries a root string index signature, so when a #5155 phase removesit,
Omitstops collapsing and the lists — plus this whole pin — become removable. One of thepin's assertions (
declaresStringIndexon the source schemas) is the tripwire that willnotice.
Ghost-assertion guard — both readings
The pin was run against unmodified
origin/mainforpackages/types/src/objectql.ts(the fix reverted from a committed state,git checkout origin/main -- <path>, restored withgit checkout HEAD -- <path>; restoreproven by an empty
git diff HEADand a matchinggit hash-object/git rev-parse HEAD:<path>pair):origin/mainTest Files 1 failed (1)·Tests 16 failed | 6 passed (22)Test Files 1 passed (1)·Tests 22 passed (22)The failure on
mainis the measurement itself, not a proxy:The 6 that still pass on
mainare the degenerate control — the source schemas stillreport 61 / 67 members and still carry the #5155 index signature. That is exactly their job: a
pin reading only the derived type would pass if both sides collapsed to zero.
Degenerate control — re-derived, not inherited
ObjectGridSchema61 andObjectFormSchema67 were measured in this pass through thechecker, not carried over from the card. Both are asserted explicitly, alongside a
declaresStringIndexassertion on each source schema.Forward-drift case — proved
A member (
driftProbe6269?: string) was temporarily added toObjectGridSchemaand left outof the key list. Mutation confirmed on disk before the run (
grepfor the injected identifier= 1 occurrence, 0 occurrences inside the key list; worktree blob hash
b47b9da9…against theHEADblob3ebeefac…), the run captured, the probe removed under anEXIT/INT/TERMtrap and the restore proven by a matching blob hash and zero residue:
Both the set-equality assertion and the degenerate control red, which is the right
shape: a deliberate member addition has to be acknowledged in two places.
Blast radius — measured, zero breakages
Restoring named members re-enables excess-property checks on object literals assigned into
these slots, so
table: { colunms: 3 }is now an error. That is the intent. What it actuallycosts in this tree:
turbo run type-check: 81 successful, 81 total, 0error TS— after a fullturbo run build(43 successful, 43 total) so every consumer resolves the new.d.tsrather than a stale one.
check:doc-snippets: 267 of 267 covered blocks judged, 0 failed, compiled against thebuilt types — that is the gate covering the 13 slot literals in
content/docs/plugins/plugin-view.mdx.object-viewschema literals, across 71candidate files — 23 in
.tsx, 6 in.jsonschema-catalog fixtures, 13 in.mdxdocs.The 16 distinct keys they use between them (
columns,defaultFilters,defaultSort,fields,filter,pageSize,pagination,selection,sort;sections,showCancel,showSubmit,subforms,submitText, pluscolumns/fieldson the form side) are allin the new key lists. Zero legitimate usages break, so there is no list for the PM to
adjudicate here.
Also measured in this pass, as the card asked:
PartialSchema< T >packages/types/src/index.ts:905—PartialSchema< T extends BaseSchema >, the generic shapethe card flagged as "not measured, and worth checking". It collapses too, for every
instantiation tried:
All four keep a live
[key: string]: any. The{ type: T['type'] }half of the intersectionis the only reason the count is 1 rather than 0; the
& Partial< Omit< T, 'type' > >halfcontributes nothing.
⛔ Not fixed here, per the dispatch order. Reported and proposed instead: filed as #6397
with the measurements, and it also carries the fact that decides it —
PartialSchemahaszero consumers, in or out of
packages/types. Grepped acrosspackages/,apps/,examples/,content/,docs/: two occurrences of the identifier, both the declaration andits own emitted copy. My recommendation on that card is retirement (option 1) or sequencing
behind #5155 (option 3) — a repair in the #6269 style is not portable, because
Tis genericand there is no literal key list to write.
Verification
All commands run at repo root. Green union measured on
642b91f87, which is this branch'sfinal commit (the merge of
origin/maintaken after the fix commit).pnpm exec turbo run build --filter="!@object-ui/site" --concurrency=2Tasks: 43 successful, 43 totalpnpm exec turbo run type-check --concurrency=2Tasks: 81 successful, 81 total, 0error TSpnpm exec vitest run packages/types/ packages/plugin-view/Test Files 85 passed (85)·Tests 935 passed (935)pnpm exec vitest run packages/types/src/__tests__/object-view-slot-key-lists.test.tsTest Files 1 passed (1)·Tests 22 passed (22)pnpm --filter @object-ui/types lint✖ 244 problems (0 errors, 244 warnings)— all pre-existingno-explicit-any; none in the added line rangepnpm run check:doc-types✅ Every documented component type is registered.pnpm run check:doc-snippetsEvery covered documentation snippet compiles against the built types.pnpm run check:control-bytes✅ check-control-bytes: OK (scanned 5282 tracked text file(s))pnpm run changeset:check✅ No changeset declares a major bump.node scripts/check-changeset-presence.mjs✅ 2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)Declared narrowing.
pnpm lintwas run per-package (--filter @object-ui/types) ratherthan repo-wide, and the repo-wide
type-check/build/ affected-package tests above weremeasured on the fix commit; only the tests and the changeset/control-byte gates were re-run on
the
origin/mainmerge head642b91f87. The merge touched 45 files and none underpackages/types/, so the pin's inputs are byte-identical between the two commits. The lintnarrowing is a measurement rather than a gap on three counts: (1) the eslint population comes
from eslint's own flat config, and this diff touches exactly one package; (2)
--format jsonover the two changed files reports 2 files linted, 0 errors, 17 warnings,all 17 at lines outside the added range (
@@ -1430,0 +1431,165 @@and the four slot-declhunks); (3)
eslint.config.jsdeclares noprojectService, noparserOptionsand noproject:, so linting is not type-aware and this type change cannot move the verdict onany file the diff does not touch. CI runs the full farm regardless.
Changeset
.changeset/6269-objectview-slot-key-lists.md—patch,@object-ui/types.Draft, and staying draft — the PM lands it.
Generated by Claude Code
Generated by Claude Code