Skip to content

Conversation

@johanrd
Copy link
Contributor

@johanrd johanrd commented Oct 3, 2025

Summary

  • Adds generic type parameters (OptionsType and CellArgs) throughout the table system for improved type safety
  • Enables strongly-typed Cell component arguments for better Glint/TypeScript inference
  • Splits CellContext into two types: CellConfigContext (for configuration) and CellContext (for runtime)
  • Exports CellContext as part of the public API

Motivation

When defining custom Cell components with custom options, there was no way to get proper type safety in Glint. This change allows developers to specify the exact shape of their Cell component arguments and options, enabling full type inference in templates.

Changes

  • Table, Column, TableConfig, ColumnConfig, and headlessTable now accept OptionsType and CellArgs generic parameters
  • CellContext split into:
    • CellConfigContext<T, OptionsType>: For defining column options (optional fields for user convenience)
    • CellContext<T, OptionsType>: For Cell components (required fields since they're always provided at runtime)
  • CellContext exported from the public API for easier type annotations

Example Usage

interface MyOptions {
  customField: string;
  anotherField: number;
}

interface MyCellArgs {
  data: MyDataType;
  column: Column<MyDataType, MyOptions>;
  options: MyOptions;
}

const table = headlessTable<MyDataType, MyOptions, MyCellArgs>(this, {
  columns: () => [{
    key: 'custom',
    Cell: MyCustomCell, // now fully typed!
    options: ({ row }) => ({
      customField: row.data.value,
      anotherField: 42
    })
  }],
  data: () => myData
});

Breaking Changes

None - the new generic parameters default to any, maintaining backward compatibility.

Introduces OptionsType and CellArgs as generic parameters across the table
system to enable type-safe Cell component signatures and custom options in Glint.

- Add OptionsType and CellArgs generics to Table, Column, and related classes
- Split CellContext into CellConfigContext (optional fields) and CellContext (required fields)
- Export CellContext as part of the public API
- Update all internal usages to support the new generic parameters
} & Record<string, unknown>;

export interface ColumnConfig<T = unknown> {
export interface ColumnConfig<T = unknown, OptionsType = any, CellArgs = any> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do knownown, are things able to be inferred (maybe not so explicitly needed?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, important question. I see the tests are failing. Will look into it (works on my machine™)

* a convenience for consumers of the headless table
*/
Cell?: ComponentLike<CellContext<T>>;
Cell?: ComponentLike<CellArgs>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T previously allowed for inferred types - does this still work?

@johanrd johanrd marked this pull request as draft November 6, 2025 12:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants