From 85028500fc591dc4dc4d428bc51935a2d316fcb1 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Fri, 17 Jul 2026 15:18:37 -0500 Subject: [PATCH] fix numeric accessor keys --- .../src/core/columns/constructColumn.ts | 8 +++--- packages/table-core/src/types/ColumnDef.ts | 2 +- packages/table-core/src/types/type-utils.ts | 2 +- .../table-core/src/worker/initTableWorker.ts | 6 ++--- .../tests/unit/helpers/columnHelper.test.ts | 27 ++++++++++++++++++- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/table-core/src/core/columns/constructColumn.ts b/packages/table-core/src/core/columns/constructColumn.ts index b9bb8975ac..35815746da 100644 --- a/packages/table-core/src/core/columns/constructColumn.ts +++ b/packages/table-core/src/core/columns/constructColumn.ts @@ -51,10 +51,12 @@ export function constructColumn< } as ColumnDefResolved<{}, TData, TValue> const accessorKey = resolvedColumnDef.accessorKey + const accessorKeyString = + accessorKey === undefined ? undefined : String(accessorKey) const id = resolvedColumnDef.id ?? - (accessorKey ? accessorKey.replaceAll('.', '_') : undefined) ?? + accessorKeyString?.replaceAll('.', '_') ?? (typeof resolvedColumnDef.header === 'string' ? resolvedColumnDef.header : undefined) @@ -63,9 +65,9 @@ export function constructColumn< if (resolvedColumnDef.accessorFn) { accessorFn = resolvedColumnDef.accessorFn - } else if (accessorKey) { + } else if (accessorKey !== undefined) { // Support deep accessor keys - if (accessorKey.includes('.')) { + if (typeof accessorKey === 'string' && accessorKey.includes('.')) { const keys = accessorKey.split('.') accessorFn = (originalRow: TData) => { let result = originalRow as Record | undefined diff --git a/packages/table-core/src/types/ColumnDef.ts b/packages/table-core/src/types/ColumnDef.ts index 7bac0b1d7e..afa9d414e2 100644 --- a/packages/table-core/src/types/ColumnDef.ts +++ b/packages/table-core/src/types/ColumnDef.ts @@ -254,5 +254,5 @@ export type ColumnDefResolved< TData extends RowData, TValue extends CellData = CellData, > = Partial>> & { - accessorKey?: string + accessorKey?: (string & {}) | keyof TData } diff --git a/packages/table-core/src/types/type-utils.ts b/packages/table-core/src/types/type-utils.ts index a63571ab9b..cf6be1c3d6 100644 --- a/packages/table-core/src/types/type-utils.ts +++ b/packages/table-core/src/types/type-utils.ts @@ -80,7 +80,7 @@ export type DeepValue = T extends Record ? TProp extends `${infer TBranch}.${infer TDeepProp}` ? DeepValue - : T[TProp & string] + : T[TProp & keyof T] : never export type NoInfer = [T][T extends any ? 0 : never] diff --git a/packages/table-core/src/worker/initTableWorker.ts b/packages/table-core/src/worker/initTableWorker.ts index 3711255f75..cf7c7fca6d 100644 --- a/packages/table-core/src/worker/initTableWorker.ts +++ b/packages/table-core/src/worker/initTableWorker.ts @@ -94,9 +94,9 @@ export function initTableWorker< .map( (def) => def.id ?? - (typeof def.accessorKey === 'string' - ? def.accessorKey.replaceAll('.', '_') - : undefined), + (def.accessorKey === undefined + ? undefined + : String(def.accessorKey).replaceAll('.', '_')), ) .filter((id): id is string => id != null) } else { diff --git a/packages/table-core/tests/unit/helpers/columnHelper.test.ts b/packages/table-core/tests/unit/helpers/columnHelper.test.ts index 6acd1f408b..2389434ff7 100644 --- a/packages/table-core/tests/unit/helpers/columnHelper.test.ts +++ b/packages/table-core/tests/unit/helpers/columnHelper.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, expectTypeOf, it } from 'vitest' import { constructTable, createColumnHelper } from '../../../src' import { testFeatures } from '../../fixtures/features' @@ -74,4 +74,29 @@ describe('createColumnHelper', () => { expect(row.getValue('shouty')).toBe('LINSLEY') expect(row.getValue('actions')).toBeUndefined() }) + + it('should resolve numeric accessor keys for tuple rows', () => { + type TupleRow = [string, number] + const tupleHelper = createColumnHelper() + const firstColumn = tupleHelper.accessor(0, { + cell: (info) => { + expectTypeOf(info.getValue()).toEqualTypeOf() + return info.getValue() + }, + }) + const secondColumn = tupleHelper.accessor(1, {}) + const table = constructTable({ + features, + columns: tupleHelper.columns([firstColumn, secondColumn]), + data: [['Alice', 42]], + }) + const row = table.getRowModel().rows[0]! + + expect(table.getAllLeafColumns().map((column) => column.id)).toEqual([ + '0', + '1', + ]) + expect(row.getValue('0')).toBe('Alice') + expect(row.getValue('1')).toBe(42) + }) })