Skip to content

Commit 66c328c

Browse files
committed
test(types): a computed Record<string, number> still assigns to grid columns; say so instead of pinning the opposite (objectui#11491)
tsc -p tsconfig.test.json measured the 8505 boundary row: TypeScript does not judge an index signature's value type against optional target members, so the computed-record escape covers values as well as keys. The row keeps its original record, the changeset and the 8505 dated note state the measured reading. Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9b7aaf7 commit 66c328c

3 files changed

Lines changed: 13 additions & 15 deletions

File tree

‎.changeset/11491-grid-columns-set.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ and `{ "columns": { "xs": 13 } }`, `"columns": 0` and `"columns": -1` drew two c
1717
nobody authored.
1818

1919
- `@object-ui/types`: `GridSchema.columns` is the literal union of 1 to 12, or a partial
20-
breakpoint map of that union, on the TypeScript face, so `tsc` refuses any other count, and a
21-
computed `Record<string, number>` no longer assigns to it. The zod mirror refuses one at
20+
breakpoint map of that union, on the TypeScript face, so `tsc` refuses any other count written
21+
as a literal (a computed `Record<string, number>` still assigns, as it did for keys since
22+
objectui#8505; the mirror judges its counts). The zod mirror refuses one at
2223
`columns` as an `invalid_union` whose message lists the set; its arms carry the set as
2324
`values`, at the breakpoint's own path for the object form. `safeValidateSchema` (what
2425
`objectui validate` runs) and the strict authoring face both give that refusal. An unknown

‎.changeset/8505-grid-columns-breakpoint-narrowing.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ an advisory sweep that never parses against the schema a file whose root carries
5353
(`children`, `className`, `body`, …), lists a file with none of those keys by name
5454
when the file does not validate, and exits non-zero on unreadable JSON only.
5555

56-
⚠️ **Dated note, 2026-10-02 — the column counts are closed too — objectui#11491.** At this change `GridSchema.columns` was `number | Partial<Record<BreakpointName, number>>`, and a computed `Record<string, number>` still assigned to it. Now each count, the bare number and every breakpoint's, is one of 1 to 12, the counts the `grid` renderer maps to a column class, on the TypeScript face and in the zod mirror. A computed record still assigns when its values are typed as those counts (the key escape described above stands); a `Record<string, number>` no longer does. `.changeset/11491-grid-columns-set.md` states what ships. The rest of this entry is kept as the reading of this change.
56+
⚠️ **Dated note, 2026-10-02 — the column counts are closed too — objectui#11491.** At this change `GridSchema.columns` was `number | Partial<Record<BreakpointName, number>>`. Now each count, the bare number and every breakpoint's, is one of 1 to 12, the counts the `grid` renderer maps to a column class, on the TypeScript face and in the zod mirror, so a literal `{ md: 13 }` stops compiling as `{ xxl: 6 }` did. The escape described above still holds, for values as well as keys: a computed `Record<string, number>` still assigns, and the zod mirror is what judges its counts. `.changeset/11491-grid-columns-set.md` states what ships. The rest of this entry is kept as the reading of this change.

‎packages/types/src/__tests__/grid-columns-breakpoint-narrowing-8505.test.ts‎

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ describe('objectui#8505 — a key outside the vocabulary no longer compiles', ()
220220
/* ── (d) the boundary: what this narrowing does NOT catch, measured ───────── */
221221

222222
describe('objectui#8505 — the narrowing broke no producer, and this is why', () => {
223-
it('a computed record of counts still assigns — index signatures satisfy optional members', () => {
223+
it('a computed `Record<string, number>` still assigns — index signatures satisfy optional members', () => {
224224
// The blast-radius question this card was dispatched with: does something
225225
// assign into `columns` from a COMPUTED record rather than a literal, and
226226
// would that go red at the call site? Measured two ways and they agree.
@@ -236,19 +236,16 @@ describe('objectui#8505 — the narrowing broke no producer, and this is why', (
236236
// package's source, test and example programs — was green with the
237237
// narrowing applied and zero call sites edited.
238238
//
239-
// ⚠️ Re-judged by objectui#11491, which closed the VALUES to the counts the
240-
// renderer maps. The escape this row pins is the KEY one and it stands: the
241-
// record below is computed, keyed by `string`, and still assigns. What no
242-
// longer assigns is a `Record<string, number>`, on purpose — its values may
243-
// be any number, and `grid` maps 1 to 12 only — so the row's record is typed
244-
// by the counts, and the refusal is pinned beside it.
245-
const computed: Record<string, ColumnCount> = { xs: 1, sm: 2 };
239+
// ⚠️ Re-read by objectui#11491, which closed the VALUES to the counts the
240+
// renderer maps, and measured with `tsc -p tsconfig.test.json`: this row
241+
// still compiles, `Record<string, number>` and all. TypeScript does not
242+
// judge an index signature's VALUE type against optional target members
243+
// either, so the escape covers values as well as keys. The TypeScript face
244+
// closes what an author writes as a literal; the zod mirror judges the
245+
// values a computed record carries (`grid-columns-set-11491.test.ts`).
246+
const computed: Record<string, number> = { xs: 1, sm: 2 };
246247
const fromComputed: GridSchema = { type: 'grid', columns: computed };
247248
expect(fromComputed.columns).toEqual({ xs: 1, sm: 2 });
248-
const anyNumber: Record<string, number> = { xs: 1, sm: 2 };
249-
// @ts-expect-error — a `number` value may be a count `grid` does not map (objectui#11491)
250-
const fromAnyNumber: GridSchema = { type: 'grid', columns: anyNumber };
251-
expect(fromAnyNumber).toBeDefined();
252249
});
253250

254251
it('a NON-fresh object with at least one valid key also still assigns', () => {

0 commit comments

Comments
 (0)