Blocked-by: #11543
This card carries objectui#8347's F1 half: the TypeScript type of a node slot and of SchemaRenderer's schema prop. objectui#8347 keeps the removal itself and everything its fork ACCEPT lists for the last PR.
Filing-gate category: ① — a named landing point (SchemaNode in @object-ui/types, SchemaRenderer's schema prop in @object-ui/react, @object-ui/core's schema builder), measured reach, and named producers, ordered by the objectui#7927 ruling's step 1. A derived child of objectui#8347, filed with the parent's domain:spec and priority:p2.
Reader: the domain:spec @ objectui seat (objectui#10217) dispatches it, and an os-dev executes it.
Parent: objectui#8347, which is pm:blocked until this card and its two siblings land.
What was measured (objectui#8347's P1 report 5953663875, at main 5988b6b53)
SchemaNode is BaseSchema | string | number | boolean | null | undefined (packages/types/src/base.ts, read on origin/main), and every node slot (children, trigger, content, a view's schema) uses it. SchemaRenderer's schema prop is BaseSchema | AuthoringNode | string | null | undefined. With BaseSchema's index signature deleted alone:
- an inline child that carries its own type's keys (a text node's
content, a statistic's value, a button's variant) stops compiling, and per-child satisfies TextSchema does not help, because the slot still excess-checks the literal against BaseSchema (measured by a type probe);
- 8 test and example literals: types
page-body-arity-8310 ×3, overlay-trigger-union-7081 ×2, @object-ui/core's schema builder ×2 (.child() takes BaseSchema), and the types example's HeaderBarSchema cast ×1;
- 17 doc diagnostics in
check:doc-snippets: schema-renderer.mdx ×3 (including a custom widget's customProp), architecture.md, quick-start.md, schema-playground.md, schema-rendering.md, enhanced-actions.mdx, building-crud-app.md and data-source.md (objectName on a detail node), the objectos-integration.mdx page template, the plugin-detail README ×3, the plugin-view README ×2, and the types README's crumbs;
check:doc-examples: SchemaNode's own docblock example (content on a BaseSchema literal).
reach: the published SchemaNode type and the SchemaRenderer prop. The named producers are the getting-started docs above and @object-ui/core's .child(). Today they compile only through the index signature.
Seat ruling: A, conditioned on a premise (inside the maintainer's veto window)
Governing text: the objectui#5250 ruling as objectui#8347's body quotes it: "the TypeScript side gets the matching authoring types without the [key: string]: any index signature ... so an invented or misspelled key is distinguishable from a declared one at the authoring site". A nested child is an authoring site.
- ① The ruling: node slots (the object arm of
SchemaNode) and SchemaRenderer's schema prop take the discriminated union of the declared node types, keyed by type (AnySchema ∪ AuthoringNode).
- Option B (keep
BaseSchema and make every nested node a pre-typed constant) pushes TypeScript authors to as casts at the authoring site, which is tolerance where the error should be refused.
- Option C (an explicit open record for children only) re-creates the index signature one level down, which the objectui#7927 removal ruling refuses.
- ② The premise, which the implementer measures first, before any other edit. Under objectui#8347's P1 mutation (the six
BaseSchema lines deleted alone), with a throwaway probe file compiled by tsc -p tsconfig.test.json:
- (a) an inline child of a declared type with a misspelled key is REFUSED, and the correctly spelled control compiles, both at a nested slot and at the
SchemaRenderer prop;
- (b) a node of a registered custom type (the
schema-renderer.mdx custom widget is the named instance) stays authorable through a mechanism that does NOT let a declared type's literal escape its own arm's excess check;
- (c) the type-check time of the
types, react and components programs is reported before and after, as a number. That is evidence for the seat, not a stop condition.
- ③ The prohibition: if (a) or (b) fails, report the fork with the probe evidence. ⛔ Do not fall back silently to B or C, ⛔ do not add an index signature or a
type: string catch-all arm at the slot, and ⛔ do not grow the card.
Constraints
- Every edit here must compile WITH the signature still present, so this card lands on its own and
main stays green. The removal stays objectui#8347's.
- The listed tests and docs move with the type: a doc block whose example now fails compiles against the new slot type, or is re-annotated with the declared node type.
- The compile-fail pin rides here: a misspelled key on a nested child is refused under the P1 mutation (assert it with the mutation applied in a probe, or with a test that declares the stripped shape locally). The correct spelling still compiles.
Clause-② is stated at claim from the actual accept-set change. With the signature present, a member union of index-signature types accepts what BaseSchema accepts today.
Dedupe
REST list of objectui's 600 most recently updated issues and PRs, open and closed (back to 2026-09-28T12:31Z), grepped locally on 2026-10-02: SchemaNode 13 hits, all closed PRs or the closed preparation card objectui#11364; "node slot / nested child type" 6 hits, none open on this question (objectui#11069 is the validate wiring); control objectui 589.
Dedupe words: SchemaNode slot union · inline child excess property BaseSchema · SchemaRenderer schema prop node union
Blocked-by: #11543
This card carries objectui#8347's F1 half: the TypeScript type of a node slot and of
SchemaRenderer'sschemaprop. objectui#8347 keeps the removal itself and everything its fork ACCEPT lists for the last PR.Filing-gate category: ① — a named landing point (
SchemaNodein@object-ui/types,SchemaRenderer'sschemaprop in@object-ui/react,@object-ui/core's schema builder), measured reach, and named producers, ordered by the objectui#7927 ruling's step 1. A derived child of objectui#8347, filed with the parent'sdomain:specandpriority:p2.Reader: the
domain:spec @ objectuiseat (objectui#10217) dispatches it, and an os-dev executes it.Parent: objectui#8347, which is
pm:blockeduntil this card and its two siblings land.What was measured (objectui#8347's P1 report
5953663875, atmain5988b6b53)SchemaNodeisBaseSchema | string | number | boolean | null | undefined(packages/types/src/base.ts, read onorigin/main), and every node slot (children,trigger,content, a view'sschema) uses it.SchemaRenderer'sschemaprop isBaseSchema | AuthoringNode | string | null | undefined. WithBaseSchema's index signature deleted alone:content, a statistic'svalue, a button'svariant) stops compiling, and per-childsatisfies TextSchemadoes not help, because the slot still excess-checks the literal againstBaseSchema(measured by a type probe);page-body-arity-8310×3,overlay-trigger-union-7081×2,@object-ui/core's schema builder ×2 (.child()takesBaseSchema), and the types example'sHeaderBarSchemacast ×1;check:doc-snippets:schema-renderer.mdx×3 (including a custom widget'scustomProp),architecture.md,quick-start.md,schema-playground.md,schema-rendering.md,enhanced-actions.mdx,building-crud-app.mdanddata-source.md(objectNameon a detail node), theobjectos-integration.mdxpage template, the plugin-detail README ×3, the plugin-view README ×2, and the types README's crumbs;check:doc-examples:SchemaNode's own docblock example (contenton aBaseSchemaliteral).reach:the publishedSchemaNodetype and theSchemaRendererprop. The named producers are the getting-started docs above and@object-ui/core's.child(). Today they compile only through the index signature.Seat ruling: A, conditioned on a premise (inside the maintainer's veto window)
Governing text: the objectui#5250 ruling as objectui#8347's body quotes it: "the TypeScript side gets the matching authoring types without the
[key: string]: anyindex signature ... so an invented or misspelled key is distinguishable from a declared one at the authoring site". A nested child is an authoring site.SchemaNode) andSchemaRenderer'sschemaprop take the discriminated union of the declared node types, keyed bytype(AnySchema∪AuthoringNode).BaseSchemaand make every nested node a pre-typed constant) pushes TypeScript authors toascasts at the authoring site, which is tolerance where the error should be refused.BaseSchemalines deleted alone), with a throwaway probe file compiled bytsc -p tsconfig.test.json:SchemaRendererprop;schema-renderer.mdxcustom widget is the named instance) stays authorable through a mechanism that does NOT let a declared type's literal escape its own arm's excess check;types,reactandcomponentsprograms is reported before and after, as a number. That is evidence for the seat, not a stop condition.type: stringcatch-all arm at the slot, and ⛔ do not grow the card.Constraints
mainstays green. The removal stays objectui#8347's.Clause-②is stated at claim from the actual accept-set change. With the signature present, a member union of index-signature types accepts whatBaseSchemaaccepts today.Dedupe
REST list of objectui's 600 most recently updated issues and PRs, open and closed (back to 2026-09-28T12:31Z), grepped locally on 2026-10-02:
SchemaNode13 hits, all closed PRs or the closed preparation card objectui#11364; "node slot / nested child type" 6 hits, none open on this question (objectui#11069 is thevalidatewiring); controlobjectui589.Dedupe words:
SchemaNode slot union·inline child excess property BaseSchema·SchemaRenderer schema prop node union