From 76dad3dd1ac08732b838dc8b76186b0e3d3d6e06 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:26:22 -0400 Subject: [PATCH] Check each column's Cell and options, and keep the cell args of declared lists - A column list with a declared type keeps its cell args, like it keeps its column meta. A shared component that takes `ColumnConfig[]` from its caller can build the table (johanrd/table#6). - Each column written in place is checked on its own: its Cell takes the row type, the column's meta and the table meta, and when the Cell asks for `@options`, the column's `options` returns them. - A table `meta` together with a callback that has parameters no longer loses the inferred cell args and column meta. The Cell check read the column list while TypeScript was still inferring it. - `CellOptions` and `CellOptionsOf` are exported (johanrd/table#5). Co-Authored-By: Claude Opus 5.5 (1M context) --- .../typing-meta-and-cells.gjs.md | 35 +++++- .../-private/-type-tests/cell-args.test.ts | 23 ++++ .../-type-tests/declared-cell-args.test.ts | 68 +++++++++++ .../-type-tests/options-check.test.ts | 109 ++++++++++++++++++ table/src/-private/interfaces/column.ts | 12 ++ table/src/-private/interfaces/table.ts | 26 ++--- table/src/-private/js-helper.ts | 2 +- table/src/-private/meta.ts | 57 ++++++++- table/src/index.ts | 2 + 9 files changed, 312 insertions(+), 22 deletions(-) create mode 100644 table/src/-private/-type-tests/declared-cell-args.test.ts create mode 100644 table/src/-private/-type-tests/options-check.test.ts diff --git a/docs-app/src/templates/1-get-started/typing-meta-and-cells.gjs.md b/docs-app/src/templates/1-get-started/typing-meta-and-cells.gjs.md index f086ec3..302ed89 100644 --- a/docs-app/src/templates/1-get-started/typing-meta-and-cells.gjs.md +++ b/docs-app/src/templates/1-get-started/typing-meta-and-cells.gjs.md @@ -224,6 +224,20 @@ columns: () => [ `column.getOptionsForRow` has the type of the `@options` that the Cells ask for, and the `defaultValue`. +TypeScript checks each column that you write in place: +a column whose Cell asks for `@options` must have an `options` that returns them. + +```ts +columns: () => [ + // error: `unit` is not a number + { key: "age", Cell: UnitCell, options: () => ({ unit: 3 }) }, + // error: the Cell asks for `@options`, and this column has no `options` + { key: "height", Cell: UnitCell }, +], +``` + +To name the types of options in your own code, import `CellOptions` (what `options` returns) and `CellOptionsOf` (the `@options` of a Cell's args). + ## Code that takes any table A function that accepts `Column` or `Table` accepts columns and tables with any meta and any cell args. @@ -237,6 +251,24 @@ function exportWidthOf(column: Column) { } ``` +## Shared table components + +A component that takes a column list from its caller and builds the table itself +can pass its type arguments through. +The table keeps the cell args, and the column metas, that the list declares: + +```ts +import type { ColumnConfig } from "@universal-ember/table"; + +function makeTable( + parent: object, + columns: ColumnConfig[], + data: Row[], +) { + return headlessTable(parent, { columns: () => columns, data: () => data }); +} +``` + ## Limits - In `value` and `options`, `column.meta` is `unknown`, because TypeScript cannot give it the inferred type there. @@ -244,5 +276,4 @@ function exportWidthOf(column: Column) { - An inline `