Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/react/kitchen-sink/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ function App() {
},
keepPinnedRows: true,
debugTable: true,
autoResetExpanded: false, // keep expanded rows during filtering changes
},
(state) => state, // default selector
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export function table_getAllLeafColumns<
table,
'getOrderColumns',
table_getOrderColumnsFn,
)(leafColumns)
)(leafColumns) as Array<Column<TFeatures, TData, unknown>>
}

/**
Expand Down
4 changes: 3 additions & 1 deletion packages/table-core/src/core/headers/buildHeaderGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ export function buildHeaderGroups<
pendingParentHeaders.push(header)
}

headerGroup.headers.push(headerToGroup)
headerGroup.headers.push(
headerToGroup as Header<TFeatures, TData, unknown>,
)
headerToGroup.headerGroup = headerGroup
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export function shouldAutoRemoveFilter<
) {
return (
(filterFn && filterFn.autoRemove
? filterFn.autoRemove(value, column as Column_Internal<TFeatures, TData>)
? filterFn.autoRemove(value, column as any)
: false) ||
typeof value === 'undefined' ||
(typeof value === 'string' && !value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { Row } from '../../types/Row'
import type { CellData, RowData, Updater } from '../../types/type-utils'
import type { TableFeatures } from '../../types/TableFeatures'
import type { Table_Internal } from '../../types/Table'
import type { Column_Internal } from '../../types/Column'
import type { Column, Column_Internal } from '../../types/Column'
import type {
ColumnPinningPosition,
ColumnPinningState,
Expand Down Expand Up @@ -364,15 +364,11 @@ export function table_getLeftHeaderGroups<
TData extends RowData,
>(table: Table_Internal<TFeatures, TData>) {
const allColumns = table.getAllColumns()
const leafColumnsById = table.getAllLeafColumnsById() as Record<
string,
Column_Internal<TFeatures, TData, unknown>
>
const leafColumnsById = table.getAllLeafColumnsById()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Type cast removal at line 367 reflects Column_Internal narrowing.

The explicit cast previously applied to leafColumnsById has been removed, and at lines 371 and 405, the orderedLeafColumns arrays now use the public Column<TFeatures, TData, unknown> type instead of Column_Internal<...>.

This change is consistent with the Column_Internal type narrowing in Column.ts (lines 45-51): since Column_Internal no longer includes feature-specific types, this code switched to the public Column type to preserve the full type contract.

However, this creates an inconsistency with columnFilteringFeature.utils.ts and globalFilteringFeature.utils.ts, which use as any casts instead of switching to Column. The mixed approaches suggest the type refactor may not have a consistent resolution strategy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/table-core/src/features/column-pinning/columnPinningFeature.utils.ts`
at line 367, There is a type handling inconsistency across feature utility files
following the Column_Internal type narrowing refactor. In
columnPinningFeature.utils.ts, the explicit type cast was removed and the code
uses the public Column type instead, but in columnFilteringFeature.utils.ts and
globalFilteringFeature.utils.ts, as any casts are still being used. Update
columnFilteringFeature.utils.ts and globalFilteringFeature.utils.ts to follow
the same pattern as columnPinningFeature.utils.ts: remove the as any casts
applied to orderedLeafColumns or similar column array variables, and instead
rely on the public Column type (Column<TFeatures, TData, unknown>) to preserve
the full type contract after the Column_Internal narrowing refactor, ensuring
consistent type handling across all three files.

const { left } =
table.atoms.columnPinning?.get() ?? getDefaultColumnPinningState()

const orderedLeafColumns: Array<Column_Internal<TFeatures, TData, unknown>> =
[]
const orderedLeafColumns: Array<Column<TFeatures, TData, unknown>> = []
for (let i = 0; i < left.length; i++) {
const column = leafColumnsById[left[i]!]
if (
Expand Down Expand Up @@ -402,15 +398,11 @@ export function table_getRightHeaderGroups<
TData extends RowData,
>(table: Table_Internal<TFeatures, TData>) {
const allColumns = table.getAllColumns()
const leafColumnsById = table.getAllLeafColumnsById() as Record<
string,
Column_Internal<TFeatures, TData, unknown>
>
const leafColumnsById = table.getAllLeafColumnsById()
const { right } =
table.atoms.columnPinning?.get() ?? getDefaultColumnPinningState()

const orderedLeafColumns: Array<Column_Internal<TFeatures, TData, unknown>> =
[]
const orderedLeafColumns: Array<Column<TFeatures, TData, unknown>> = []
for (let i = 0; i < right.length; i++) {
const column = leafColumnsById[right[i]!]
if (
Expand Down Expand Up @@ -446,7 +438,7 @@ export function table_getCenterHeaderGroups<
table,
'getVisibleLeafColumns',
table_getVisibleLeafColumns,
) as unknown as Array<Column_Internal<TFeatures, TData, unknown>>
)
const { left, right } =
table.atoms.columnPinning?.get() ?? getDefaultColumnPinningState()
const leftAndRight: Array<string> = [...left, ...right]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,8 @@ export interface Table_ColumnResizing {
resetHeaderSizeInfo: (defaultState?: boolean) => void
/**
* Updates transient resize interaction state with a next state or updater function.
*
* The lowercase `c` in this API name matches the current generated v9 table
* API for the `columnResizing` state slice.
*/
setcolumnResizing: (updater: Updater<columnResizingState>) => void
setColumnResizing: (updater: Updater<columnResizingState>) => void
}

export interface ColumnDef_ColumnResizing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function column_getCanGlobalFilter<
(column.columnDef.enableGlobalFilter ?? true) &&
(column.table.options.enableGlobalFilter ?? true) &&
(column.table.options.enableFilters ?? true) &&
(column.table.options.getColumnCanGlobalFilter?.(column) ?? true) &&
(column.table.options.getColumnCanGlobalFilter?.(column as any) ?? true) &&
!!column.accessorFn
)
}
Expand Down
8 changes: 4 additions & 4 deletions packages/table-core/src/helpers/columnHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import type {
IdentifiedColumnDef,
} from '../types/ColumnDef'

export type ColumnHelper<
TFeatures extends TableFeatures,
TData extends RowData,
> = {
export interface ColumnHelper<
in out TFeatures extends TableFeatures,
in out TData extends RowData,
> {
/**
* Creates a data column definition with an accessor key or function to extract the cell value.
* @example
Expand Down
8 changes: 4 additions & 4 deletions packages/table-core/src/types/Column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export type Column<
> = Column_Core<TFeatures, TData, TValue> &
ExtractFeatureMapTypes<TFeatures, Column_FeatureMap<TFeatures, TData>>

export type Column_Internal<
TFeatures extends TableFeatures,
TData extends RowData,
export interface Column_Internal<
in out TFeatures extends TableFeatures,
in out TData extends RowData,
TValue = unknown,
> = Column<TFeatures, TData, TValue> & {
> extends Omit<Column_Core<TFeatures, TData, TValue>, 'columnDef'> {
columnDef: ColumnDefBase_All<TFeatures, TData, TValue>
}
Comment on lines +45 to 51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Identify all Column_Internal usages and `as any` casts related to column types
echo "=== All Column_Internal usages ==="
rg -n 'Column_Internal<' --type=ts -C 1

echo ""
echo "=== Column type casts to any (potential type gaps) ==="
rg -n 'column.*as any' --type=ts -C 2

echo ""
echo "=== FilterFn and callback signatures expecting column parameters ==="
rg -nP 'autoRemove.*\(|getColumnCanGlobalFilter.*\(' --type=ts -C 2

Repository: TanStack/table

Length of output: 50370


🏁 Script executed:

# Read the Column_Internal definition and related types
cat -n packages/table-core/src/types/Column.ts | sed -n '40,65p'

Repository: TanStack/table

Length of output: 561


🏁 Script executed:

# Look at FilterFn type definition and autoRemove signature
rg -n 'interface FilterFn|type FilterFn' --type=ts -A 10

Repository: TanStack/table

Length of output: 3792


🏁 Script executed:

# Find getColumnCanGlobalFilter callback signature
rg -n 'getColumnCanGlobalFilter' packages/table-core/src --type=ts -B 2 -A 2

Repository: TanStack/table

Length of output: 2502


🏁 Script executed:

# Find ColumnFilterAutoRemoveTestFn definition
rg -n 'ColumnFilterAutoRemoveTestFn' packages/table-core/src --type=ts -B 1 -A 5

Repository: TanStack/table

Length of output: 1677


🏁 Script executed:

# Get the full getColumnCanGlobalFilter signature
rg -n 'getColumnCanGlobalFilter' packages/table-core/src/features/global-filtering/globalFilteringFeature.types.ts -A 8

Repository: TanStack/table

Length of output: 346


🏁 Script executed:

# Check if Column_Internal ever intersected with Column (check git or find evidence of expected type)
cat -n packages/table-core/src/types/Column.ts | sed -n '39,75p'

Repository: TanStack/table

Length of output: 603


🏁 Script executed:

# Verify these are the only two production code as any casts related to this issue
# Filter out test files and examples
rg -n 'column.*as any' packages/table-core/src --type=ts | grep -v test | grep -v example

Repository: TanStack/table

Length of output: 359


🏁 Script executed:

# Check context around the function that uses these callbacks
cat -n packages/table-core/src/features/column-filtering/columnFilteringFeature.utils.ts | sed -n '310,335p'

Repository: TanStack/table

Length of output: 773


Type narrowing in Column_Internal causes downstream type-safety gaps.

The type definition of Column_Internal extends only Omit<Column_Core<...>, 'columnDef'>, omitting the ExtractFeatureMapTypes intersection present in the broader Column type. This forces two callback functions to suppress type safety with as any casts:

  • packages/table-core/src/features/column-filtering/columnFilteringFeature.utils.ts#L326: Casts column to any when passing to filterFn.autoRemove, which expects Column<TFeatures, TData, TValue> (line 83 of columnFilteringFeature.types.ts).
  • packages/table-core/src/features/global-filtering/globalFilteringFeature.utils.ts#L29: Casts column to any when passing to getColumnCanGlobalFilter, which expects Column<TFeatures, TData, TValue> (line 52 of globalFilteringFeature.types.ts).

Adjust the callback signatures to accept Column_Internal explicitly rather than relying on any to suppress the type mismatch.

📍 Affects 3 files
  • packages/table-core/src/types/Column.ts#L45-L51 (this comment)
  • packages/table-core/src/features/column-filtering/columnFilteringFeature.utils.ts#L326-L326
  • packages/table-core/src/features/global-filtering/globalFilteringFeature.utils.ts#L29-L29
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/table-core/src/types/Column.ts` around lines 45 - 51, The type
narrowing in Column_Internal omits the ExtractFeatureMapTypes intersection
present in the broader Column type, causing type mismatches. Update the callback
function signatures that currently expect Column to instead accept
Column_Internal: In columnFilteringFeature.types.ts (where filterFn.autoRemove
is defined around line 83), change the parameter type to Column_Internal, and in
globalFilteringFeature.types.ts (where getColumnCanGlobalFilter is defined
around line 52), change the parameter type to Column_Internal. Then remove the
as any casts at the call sites in columnFilteringFeature.utils.ts (line 326) and
globalFilteringFeature.utils.ts (line 29) respectively, since the types will now
match correctly.

8 changes: 4 additions & 4 deletions packages/table-core/src/types/HeaderGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface HeaderGroup_Core<
in out TData extends RowData,
> extends HeaderGroup_Header<TFeatures, TData> {}

export type HeaderGroup<
TFeatures extends TableFeatures,
TData extends RowData,
> = HeaderGroup_Core<TFeatures, TData>
export interface HeaderGroup<
in out TFeatures extends TableFeatures,
in out TData extends RowData,
> extends HeaderGroup_Core<TFeatures, TData> {}
10 changes: 5 additions & 5 deletions packages/table-core/src/types/RowModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ export type CachedRowModels<
CachedRowModels_FeatureMap<TFeatures, TData>
>

export type CachedRowModel_All<
TFeatures extends TableFeatures,
TData extends RowData = any,
> = Partial<
export interface CachedRowModel_All<
in out TFeatures extends TableFeatures,
in out TData extends RowData = any,
> extends Partial<
CachedRowModel_Core<TFeatures, TData> &
CachedRowModel_Expanded<TFeatures, TData> &
CachedRowModel_Faceted<TFeatures, TData> &
CachedRowModel_Filtered<TFeatures, TData> &
CachedRowModel_Grouped<TFeatures, TData> &
CachedRowModel_Paginated<TFeatures, TData> &
CachedRowModel_Sorted<TFeatures, TData>
>
> {}
10 changes: 5 additions & 5 deletions packages/table-core/src/types/RowModelFns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export type RowModelFns<
ExtractFeatureMapTypes<TFeatures, RowModelFns_FeatureMap<TFeatures, TData>>
>

export type RowModelFns_All<
TFeatures extends TableFeatures,
TData extends RowData,
> = Partial<
export interface RowModelFns_All<
in out TFeatures extends TableFeatures,
in out TData extends RowData,
> extends Partial<
RowModelFns_ColumnFiltering<TFeatures, TData> &
RowModelFns_ColumnGrouping<TFeatures, TData> &
RowModelFns_RowSorting<TFeatures, TData>
>
> {}
43 changes: 11 additions & 32 deletions packages/table-core/src/types/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ import type { DebugOptions, TableOptions_All } from './TableOptions'
* The core table object that only includes the core table functionality such as column, header, row, and table APIS.
* No features are included.
*/
export type Table_Core<
TFeatures extends TableFeatures,
TData extends RowData,
> = Table_Table<TFeatures, TData> &
Table_Columns<TFeatures, TData> &
Table_Rows<TFeatures, TData> &
Table_RowModels<TFeatures, TData> &
Table_Headers<TFeatures, TData>
export interface Table_Core<
in out TFeatures extends TableFeatures,
in out TData extends RowData,
>
extends
Table_Table<TFeatures, TData>,
Table_Columns<TFeatures, TData>,
Table_Rows<TFeatures, TData>,
Table_RowModels<TFeatures, TData>,
Table_Headers<TFeatures, TData> {}

export interface Table_FeatureMap<
in out TFeatures extends TableFeatures,
Expand Down Expand Up @@ -88,15 +90,6 @@ type Table_InternalBroadenedKeys =

/**
* Internal broad table shape used by feature implementations.
*
* Declared as an interface extending every stock feature's table API (rather
* than the feature-conditional `Table` intersection) so that the compiler can
* relate `Table_Internal` instantiations nominally instead of structurally
* re-expanding the feature-map conditional for every internal call site.
* Mirrors the `*_All` convention used for options, state, and row models.
* Type parameters are annotated `in out` (invariant) so the checker can relate
* instantiations by their type arguments without measuring variance or falling
* back to member-by-member structural comparison.
*/
export interface Table_Internal<
in out TFeatures extends TableFeatures,
Expand All @@ -107,21 +100,7 @@ export interface Table_Internal<
Table_Columns<TFeatures, TData>,
Table_Rows<TFeatures, TData>,
Table_RowModels<TFeatures, TData>,
Table_Headers<TFeatures, TData>,
Table_ColumnFiltering,
Table_ColumnGrouping<TFeatures, TData>,
Table_ColumnOrdering<TFeatures, TData>,
Table_ColumnPinning<TFeatures, TData>,
Table_ColumnResizing,
Table_ColumnSizing,
Table_ColumnVisibility<TFeatures, TData>,
Table_ColumnFaceting<TFeatures, TData>,
Table_GlobalFiltering<TFeatures, TData>,
Table_RowExpanding<TFeatures, TData>,
Table_RowPagination<TFeatures, TData>,
Table_RowPinning<TFeatures, TData>,
Table_RowSelection<TFeatures, TData>,
Table_RowSorting<TFeatures, TData> {
Table_Headers<TFeatures, TData> {
_rowModels: CachedRowModel_All<TFeatures, TData>
_rowModelFns: RowModelFns_All<TFeatures, TData>
options: DebugOptions<TableFeatures> &
Expand Down
16 changes: 15 additions & 1 deletion packages/table-core/src/types/TableState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,18 @@ export type TableState<TFeatures extends TableFeatures> =
* Feature internals use this when they may need to inspect optional slices owned
* by other features.
*/
export type TableState_All = Partial<TableState<TableFeatures>>
export interface TableState_All extends Partial<
TableState_ColumnFiltering &
TableState_ColumnGrouping &
TableState_ColumnOrdering &
TableState_ColumnPinning &
TableState_ColumnResizing &
TableState_ColumnSizing &
TableState_ColumnVisibility &
TableState_GlobalFiltering &
TableState_RowExpanding &
TableState_RowPagination &
TableState_RowPinning &
TableState_RowSelection &
TableState_RowSorting
> {}
21 changes: 17 additions & 4 deletions packages/table-core/tests/helpers/rowPinningHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { table } from 'node:console'
import { vi } from 'vitest'
import { getDefaultRowPinningState } from '../../src/features/row-pinning/rowPinningFeature.utils'
import {
getDefaultRowPinningState,
table_setRowPinning,
} from '../../src/features/row-pinning/rowPinningFeature.utils'
import {
constructTable,
coreFeatures,
Expand All @@ -9,7 +13,14 @@ import {
import { generateTestData } from '../fixtures/data/generateTestData'
import { storeReactivityBindings } from '../../src/store-reactivity-bindings'
import { generateTestTableWithData } from './generateTestTable'
import type { ColumnDef, RowPinningState, TableOptions } from '../../src'
import type {
ColumnDef,
RowPinningState,
StockFeatures,
TableOptions,
Table_Internal,
Table_RowPinning,
} from '../../src'
import type { Person } from '../fixtures/data/types'

// Define feature set with proper typing
Expand Down Expand Up @@ -52,15 +63,17 @@ export function createTableWithPinningState(
}

export function createTableWithMockOnPinningChange(rowCount = 10): {
table: ReturnType<typeof generateTestTableWithData>
table: Table_Internal<StockFeatures, Person> &
Table_RowPinning<StockFeatures, Person>
onRowPinningChangeMock: ReturnType<typeof vi.fn>
} {
const onRowPinningChangeMock = vi.fn()
const table = generateTestTableWithData(rowCount, {
features: {
rowPinning: rowPinningFeature,
},
} as any)
} as any) as Table_Internal<StockFeatures, Person> &
Table_RowPinning<StockFeatures, Person>
table.options.onRowPinningChange = onRowPinningChangeMock
return { table, onRowPinningChangeMock }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ describe('row methods', () => {
const { table, onRowPinningChangeMock } =
createTableWithMockOnPinningChange()
// Set up initial state with a pinned row
table.baseAtoms.rowPinning!.set({
table.baseAtoms.rowPinning.set({
top: [ROW[0]],
bottom: [],
})
Expand Down
13 changes: 11 additions & 2 deletions packages/table-core/tests/unit/core/tableAtoms.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import { storeReactivityBindings } from '../../../src/store-reactivity-bindings'
import type {
PaginationState,
SortingState,
TableFeatures,
Table_Internal,
Table_RowPagination,
Table_RowSorting,
} from '../../../src'

const features = {
Expand All @@ -20,7 +23,11 @@ const features = {
rowSortingFeature,
}

function makeTable(options: any = {}) {
function makeTable<TFeatures extends TableFeatures>(
options: any = {},
): Table_Internal<TFeatures, any> &
Table_RowSorting<TFeatures, any> &
Table_RowPagination<TFeatures, any> {
return constructTable({
features: {
...coreFeatures,
Expand All @@ -30,7 +37,9 @@ function makeTable(options: any = {}) {
columns: [],
data: [],
...options,
}) as unknown as Table_Internal<typeof features, any>
}) as unknown as Table_Internal<TFeatures, any> &
Table_RowSorting<TFeatures, any> &
Table_RowPagination<TFeatures, any>
}

describe('three-layer atom architecture', () => {
Expand Down
Loading
Loading