Found while repairing packages/plugin-detail/README.md for objectui#5174 batch 17 (PR opened from claude/issue-5174-ungated-docs-batch17). Filed unassigned and NOT repaired there — that batch is scoped to making the README's fenced blocks compile, and this is a shipped-type question a maintainer should settle.
What
@object-ui/types declares the related-list column slot as a typed array:
// packages/types/src/views.ts -> DetailViewSchema
related?: Array<{
title: string;
type: 'list' | 'grid' | 'table';
api?: string;
columns?: TableColumn[]; // TableColumn = { header: string; accessorKey: string; ... }
...
}>;
But packages/plugin-detail/src/RelatedList.tsx normalizes bare-string entries on purpose, and says so in its own comment:
// Normalize bare-string column entries (e.g. `'user_agent'`) into the
// `{accessorKey, header}` shape the data-table renderer expects, and attach
// a type-aware cell renderer resolved from the object schema.
// Without this, page authors passing `columns: ['status', 'amount']`
// would see raw values (e.g. `planned`, unformatted numbers).
const normalizeColumn = (c: any): any => {
if (typeof c !== 'string') { ... }
const fieldDef = objectSchema?.fields?.[c] as any;
...
};
So the string branch is not accidental tolerance — it resolves the field def, derives a header from the object schema's label, and attaches a type-aware cell renderer. It is the nicer authoring form, and the one the README taught until batch 17 corrected the document to the declared type.
Why it matters
The two halves point opposite ways, and a TypeScript author gets the worse one:
- Writing
columns: ['name', 'email'] — the form the renderer optimizes for, and the form that gets object-schema labels and cell renderers for free — does not type-check against DetailViewSchema.
- Writing
columns: [{ accessorKey: 'name', header: 'Name' }] type-checks, but hand-writes headers the string branch would have resolved from the object schema, so the header stops following a field's label rename.
This is only reachable through the typed authoring path; JSON metadata arriving over the wire is unaffected.
The choice, which is why this is filed rather than fixed
- Widen the declared type to
Array-of (TableColumn or string), matching what the renderer has always accepted. Cheap, and it makes the shorter form documentable again — but it is a published-contract change on @object-ui/types.
- Retire the string branch in
RelatedList.tsx and keep the type as-is. That deletes a deliberate convenience and would break any author already passing strings.
I could not tell which is intended: the type says one thing, the renderer's comment argues for the other, and neither names the other. Whichever is chosen, the two should stop disagreeing.
Related: objectui#5174 (the batch that surfaced it), objectui#4286 (a different type-versus-runtime split on the same synthesized rail page — the aside region's className).
Filed by the domain:devx os-dev seat, session session_01MM7kaS4dPpYHV5BsMyu4tQ, as an out-of-scope finding from objectui#5174 batch 17. A dedup search ran first and found no open card for it.
Found while repairing
packages/plugin-detail/README.mdfor objectui#5174 batch 17 (PR opened fromclaude/issue-5174-ungated-docs-batch17). Filed unassigned and NOT repaired there — that batch is scoped to making the README's fenced blocks compile, and this is a shipped-type question a maintainer should settle.What
@object-ui/typesdeclares the related-list column slot as a typed array:But
packages/plugin-detail/src/RelatedList.tsxnormalizes bare-string entries on purpose, and says so in its own comment:So the string branch is not accidental tolerance — it resolves the field def, derives a header from the object schema's label, and attaches a type-aware cell renderer. It is the nicer authoring form, and the one the README taught until batch 17 corrected the document to the declared type.
Why it matters
The two halves point opposite ways, and a TypeScript author gets the worse one:
columns: ['name', 'email']— the form the renderer optimizes for, and the form that gets object-schema labels and cell renderers for free — does not type-check againstDetailViewSchema.columns: [{ accessorKey: 'name', header: 'Name' }]type-checks, but hand-writes headers the string branch would have resolved from the object schema, so the header stops following a field's label rename.This is only reachable through the typed authoring path; JSON metadata arriving over the wire is unaffected.
The choice, which is why this is filed rather than fixed
Array-of (TableColumn or string), matching what the renderer has always accepted. Cheap, and it makes the shorter form documentable again — but it is a published-contract change on@object-ui/types.RelatedList.tsxand keep the type as-is. That deletes a deliberate convenience and would break any author already passing strings.I could not tell which is intended: the type says one thing, the renderer's comment argues for the other, and neither names the other. Whichever is chosen, the two should stop disagreeing.
Related: objectui#5174 (the batch that surfaced it), objectui#4286 (a different type-versus-runtime split on the same synthesized rail page — the
asideregion'sclassName).Filed by the
domain:devxos-dev seat, sessionsession_01MM7kaS4dPpYHV5BsMyu4tQ, as an out-of-scope finding from objectui#5174 batch 17. A dedup search ran first and found no open card for it.