You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
finding(types): ObjectViewSchema's table and form slots declare ZERO properties — the same Omit-under-index-signature collapse as #6151, in property position #6269
⚠️ Generic parameters are written spaced (Omit< T, K >) throughout — GitHub's body
sanitizer eats a fragment that opens with an identifier in angle brackets, which is what
mangled #6151's first revision.
Measured while fixing #6151 (PR #6267). Filed unassigned, deliberately not fixed there:
the mechanism is identical but the correct replacement shape is a design question, not the
mechanical move #6151 took.
The fact
packages/types/src/objectql.ts declares two slots by deriving from a schema type:
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 ObjectGridSchema and ObjectFormSchema inherit BaseSchema's [key: string]: any
(#5155), so the Pick rebuilds a type holding the index signature and none of the named
members.
#6151 was this collapse in a heritage clause (interface StackSchema extends Omit< … >).
This is the same collapse in property position, which is why #6151's fix does not reach
it and why its new guard does not cover it: that guard walks the LayoutSchema union, and
these are properties on ObjectViewSchema, not union members.
What it costs
Partial< Omit< … > > of a collapsed type is a bare index signature, so the slot accepts anything: table: { colunms: 3 } (typo), table: { pageSize: 'ten' }, table: 42's
object cousins — all type-check. And editor completion inside table: { … } offers nothing
at all, so an author writing a view has no discoverable surface for a slot documented as
"Inherits from ObjectGridSchema". The declaration promises inheritance and delivers any.
Same shape of harm as #6151, and the same reason it survived: nothing errors, because the
index signature answers every key.
Why this is not a mechanical fix
#6151 could lift the shared members into an index-signature-free interface because FlexSchema and StackSchema are peers with an identical member set. These two are not
that shape:
The slots deliberately exclude identity keys (type, objectName, mode) — the
intent is "the grid's configuration, minus what the view already fixes". Restoring that
intent needs a decision about which keys are configuration, and ObjectGridSchema has
61 of them.
Partial< … > on top means the fix must preserve "all optional" while restoring the
member names.
Pick with an explicit key list instead of Omit — Pick with literal keys never
computes keyof T, so it does not collapse. Immediate and safe, but the key list is a
duplicate to keep in sync.
These two are the ones measured. The rest of the Omit population in packages/types/src
was swept in #6267 and is healthy: the three other heritage clauses (DashboardWidgetSchema, ActionParam, NavigationArea) Omit over @objectstack/spec types that carry no index
signature, and data-protocol.ts:933's BaseValidation is fine for the same reason. ⚠️index.ts:900 has a generic & Partial< Omit< T, 'type' > > whose behaviour depends on
what T is instantiated with — not measured, and worth checking as part of any fix here.
Refs: #6151 (same mechanism, heritage clause, fixed in #6267) · #5155 (the index signature)
· #6143 (where the class first surfaced).
Omit< T, K >) throughout — GitHub's bodysanitizer eats a fragment that opens with an identifier in angle brackets, which is what
mangled #6151's first revision.
Measured while fixing #6151 (PR #6267). Filed unassigned, deliberately not fixed there:
the mechanism is identical but the correct replacement shape is a design question, not the
mechanical move #6151 took.
The fact
packages/types/src/objectql.tsdeclares two slots by deriving from a schema type:table?: Partial< Omit< ObjectGridSchema, 'type' | 'objectName' > >form?: Partial< Omit< ObjectFormSchema, 'type' | 'objectName' | 'mode' > >Both derived types declare zero properties. Measured against the built
distthroughthe TypeScript checker:
61 to 0.
Why — the same mechanism as #6151
Omit< T, K >isPick< T, Exclude< keyof T, K > >, andkeyof Ton a type carrying astring index signature is
string | number— the literal member names are absorbed. BothObjectGridSchemaandObjectFormSchemainheritBaseSchema's[key: string]: any(#5155), so the
Pickrebuilds a type holding the index signature and none of the namedmembers.
#6151 was this collapse in a heritage clause (
interface StackSchema extends Omit< … >).This is the same collapse in property position, which is why #6151's fix does not reach
it and why its new guard does not cover it: that guard walks the
LayoutSchemaunion, andthese are properties on
ObjectViewSchema, not union members.What it costs
Partial< Omit< … > >of a collapsed type is a bare index signature, so the slot acceptsanything:
table: { colunms: 3 }(typo),table: { pageSize: 'ten' },table: 42'sobject cousins — all type-check. And editor completion inside
table: { … }offers nothingat all, so an author writing a view has no discoverable surface for a slot documented as
"Inherits from ObjectGridSchema". The declaration promises inheritance and delivers
any.Same shape of harm as #6151, and the same reason it survived: nothing errors, because the
index signature answers every key.
Why this is not a mechanical fix
#6151 could lift the shared members into an index-signature-free interface because
FlexSchemaandStackSchemaare peers with an identical member set. These two are notthat shape:
type,objectName,mode) — theintent is "the grid's configuration, minus what the view already fixes". Restoring that
intent needs a decision about which keys are configuration, and
ObjectGridSchemahas61 of them.
Partial< … >on top means the fix must preserve "all optional" while restoring themember names.
because everything is
anymay start erroring. That needs the same downstream sweepfix(types): StackSchema ships its declared members instead of collapsing under BaseSchema's index signature #6267 did, and possibly a ledger.
Options, none ruled here:
BaseSchema, the finding(types):StackSchema, declared as Omit-of-FlexSchema-minus-type, erases every named member — it ships declaring onlytype, because Omit collapses underBaseSchema's index signature #6151 route — correct, butneeds someone to partition
ObjectGridSchema's 61 members into "identity" and"configuration".
Pickwith an explicit key list instead ofOmit—Pickwith literal keys nevercomputes
keyof T, so it does not collapse. Immediate and safe, but the key list is aduplicate to keep in sync.
[key: string]: anyleaves every component schema open, so a "declare the surface" fix can never reject a misspelled TOP-LEVEL key #5155 (the phased zod.strict()ruling), which removes the indexsignature at the root and closes this class everywhere at once.
Scope
These two are the ones measured. The rest of the
⚠️
Omitpopulation inpackages/types/srcwas swept in #6267 and is healthy: the three other heritage clauses (
DashboardWidgetSchema,ActionParam,NavigationArea)Omitover@objectstack/spectypes that carry no indexsignature, and
data-protocol.ts:933'sBaseValidationis fine for the same reason.index.ts:900has a generic& Partial< Omit< T, 'type' > >whose behaviour depends onwhat
Tis instantiated with — not measured, and worth checking as part of any fix here.Refs: #6151 (same mechanism, heritage clause, fixed in #6267) · #5155 (the index signature)
· #6143 (where the class first surfaced).