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
Found while implementing #6373 (typing ObjectDataTable's column emit against the TableColumn[] slot it fills). Filed unassigned. Deliberately NOT absorbed into #6373, whose fence is what a PRODUCER writes; this is the same slot seen from the other end.
Measured (at 9602dc820)
packages/components/src/renderers/complex/data-table.tsx, comments stripped, every col.<key> read:
key
reads
declared by TableColumn?
accessorKey
28
yes
width
6
yes
align
5
yes
header
4
yes
className
4
yes
sortable
3
yes
editable
3
yes
cell
2
yes
cellClassName / resizable / type
1 each
yes
name
2
no — the alias #5120 holds, deliberately and documented
An author writing { accessorKey: 'x', headerIcon: <Icon/> } on a data-table column gets a compile error for a key the renderer honours, and TableColumnSchema.parse silently strips it — while the same key placed there by an untyped producer works. So the runtime admits a vocabulary the declaration refuses: the second de-facto contract AGENTS.md #0.1 forbids, in the direction where the CONSUMER is the one out of step.
Apply the rule #6373's PR states, in the declare branch this time: a key the consumer reads gets declared on TableColumn (interface + TableColumnSchema mirror + the zod-mirror-parity pairing), and the as any at the two fitContent sites goes with it. The alternative — retiring the reads — is a behaviour change and needs the usual measurement of who authors these keys today.
Found while implementing #6373 (typing
ObjectDataTable's column emit against theTableColumn[]slot it fills). Filed unassigned. Deliberately NOT absorbed into #6373, whose fence is what a PRODUCER writes; this is the same slot seen from the other end.Measured (at
9602dc820)packages/components/src/renderers/complex/data-table.tsx, comments stripped, everycol.<key>read:TableColumn?accessorKeywidthalignheaderclassNamesortableeditablecellcellClassName/resizable/typenameheaderIconfitContentTableColumn(packages/types/src/data-display.ts:293) declares exactly:header,accessorKey,className,cellClassName,width,minWidth,align,fixed,type,sortable,filterable,resizable,editable,cell.Both undeclared reads are live, not vestigial:
headerIcon— rendered into the header cell (data-table.tsx:1633-1634).fitContent— drives the auto-width pass (:575,:583) and thewidth:1%+ nowrap cell at two render sites (:1562,:1803). Both of those two go through(col as any).fitContent, which is the shape "declared != enforced" takes in TypeScript and the same tell finding(types):TableColumn.typedisagrees three ways — interface declares 8 literals, zod mirror accepts any string, renderer's live read set handles values outside the union via anas anycast #5853 removed fortype.Why it matters
An author writing
{ accessorKey: 'x', headerIcon: <Icon/> }on adata-tablecolumn gets a compile error for a key the renderer honours, andTableColumnSchema.parsesilently strips it — while the same key placed there by an untyped producer works. So the runtime admits a vocabulary the declaration refuses: the second de-facto contract AGENTS.md #0.1 forbids, in the direction where the CONSUMER is the one out of step.Not a duplicate
generateColumns()is untyped (any[]), so nothing type-checks what it writes intoDataTableSchema.columns: TableColumn[]— the hole that hid #5853 and #5453 #6004 namesheaderIconamong the keysObjectGrid.generateColumns()attaches, and its remedy is producer-side typing. Its verdict onheaderIcondecides one of these two keys and the two must agree — butfitContentis not in its list, and neither is the consumer-side read census this card is about.wrapinto the DataTable column object, but nothing indata-table.tsxever reads it #5453 is the opposite case: a key (wrap) that is forwarded and read by nobody. Its evidence table citesfitContent's read-count as the counter-probe that the grep works, without noting thatfitContentis itself undeclared.ObjectDataTable's emit seam;table-declared-equals-enforced.test.tsxis the consumer-side instrument, but it covers only the statictablerenderer's narrow surface (finding(components): the statictablerenderer reads 9 of the 20 keysTableSchema/TableColumndeclare —hoverable,striped,align,sortable,celland 6 more are inert, and the reference page documents two of them as working #5474, Option C), neverdata-table's rich one.Suggested disposition
Apply the rule #6373's PR states, in the declare branch this time: a key the consumer reads gets declared on
TableColumn(interface +TableColumnSchemamirror + thezod-mirror-paritypairing), and theas anyat the twofitContentsites goes with it. The alternative — retiring the reads — is a behaviour change and needs the usual measurement of who authors these keys today.Related
generateColumns()is untyped (any[]), so nothing type-checks what it writes intoDataTableSchema.columns: TableColumn[]— the hole that hid #5853 and #5453 #6004 —headerIconalso appears in its key triage (parent of finding(plugin-dashboard): ObjectDataTable's enrich() spreads a FieldMeta into the TableColumn[] slot, writing seven keys TableColumn does not declare #6373)wrapinto the DataTable column object, but nothing indata-table.tsxever reads it #5453 — the mirror case: a forwarded key nothing readstablerenderer reads 9 of the 20 keysTableSchema/TableColumndeclare —hoverable,striped,align,sortable,celland 6 more are inert, and the reference page documents two of them as working #5474 — the static table's declared = enforced split, whose instrument this surface lackscol.name别名,而唯一在交付前解析列身份的生产者只有 RelatedList #5120 — thenamealias, the one undeclared read that is held on purposeGenerated by Claude Code
Generated by Claude Code