table: ColumnDef types gives typescript error

Describe the bug

Looking at the examples and docs I expect this to correctly type my columns for me. Instead I get a large error with this code:

  type Example = {
    name: string
    age: number
  }

  const columnHelper = createColumnHelper<Example>()

  const columns = useMemo<ColumnDef<Example>[]>(
    () => [
      columnHelper.accessor("name", {
        cell: (info) => info.getValue(),
      }),
      columnHelper.accessor("age", {
        cell: (info) => info.getValue(),
      }),
    ],
    [columnHelper],
  )
bild

Am I doing something wrong here?

Regards Jonathan

Your minimal, reproducible example

https://codesandbox.io/s/typescript-playground-export-forked-iqm265?file=/index.tsx

Steps to reproduce

  1. Create a type with two different types, string and name for example.
  2. Use the createColumnHelper with the type
  3. Define columns with columnHelper and type them with ColumnDef<type>

Expected behavior

I expected the Columdef to correctly type my columns.

How often does this bug happen?

Every time

Screenshots or Videos

bild

Platform

Mac OS

react-table version

v8.5.13

TypeScript version

v4.8.2

Additional context

No response

Terms & Code of Conduct

  • I agree to follow this project’s Code of Conduct
  • I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 47
  • Comments: 43 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Getting the same here, trying to convince our team to migrate to @tanstack/react-table and this is certainly getting in the way of that. I’ve defined columns as such: (nothing revolutionary)

  const columnHelper = createColumnHelper<Coffee>();

  const columns = [
    columnHelper.accessor(data => data.id, {
      id: 'id',
      cell: info => info.getValue()
    })
  ];

and have typed my generic table component as:

interface TableProps<T extends object> {
  data: T[];
  columns: ColumnDef<T>[];
}

export default function index<T extends object>({ columns, data }: TableProps<T>) {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel()
  });

(...)

But am then getting the following Type Error when passing my columns as a prop:

        Property 'accessorFn' is missing in type 'ColumnDefBase<Coffee, number> & StringHeaderIdentifier' but required in type 'AccessorFnColumnDefBase<Coffee, unknown>'.ts(2322)
types.d.ts(83, 5): 'accessorFn' is declared here.
index.tsx(6, 3): The expected type comes from property 'columns' which is declared here on type 'IntrinsicAttributes & TableProps<Coffee>'

Any advice is appreciated

react-table version: 8.10.7 @types/react-table version: 7.7.18

Hey @tannerlinsley 👋 I there any update on “any” type issue? It seems this issue is dead without being resolved for long time than I would expect. Should I open separated issue instead? We really love this library but having proper type instead of any would really help us.

I am having the same issue here. Is there a way to avoid typing any?

type Props<T> = {
  data: T[];
  columns: ColumnDef<T, any>[];
};

I am having the same issue here. Is there a way to avoid typing any?

type Props<T> = {
  data: T[];
  columns: ColumnDef<T, any>[];
};

Still facing this issue

It becomes an issue when passing columns to a component as a prop.

Pre-typing would be helpful for public interfaces e.g. if we create a wrapper components with columns and data props. I am using this here right now:

interface DataTableProps {
  // FIXME: Can we figure out something more type restrictive which actually works?
  data: unknown[]
  columns: ColumnDef<any, any>[];
}

That makes TypeScript “happy”… but I would prefer something more strict.

I guess I was looking for a typed CustomTableComponent example which uses TanStack/Table underneath.

Bump.

Pre-typing would be helpful for public interfaces e.g. if we create a wrapper components with columns and data props. I am using this here right now:

This! We’re making a custom MyTableComponent and expose columns as prop that is pre-typed.

still waiting for the official fix lol

@tannerlinsley if you’re saying @Jontii 's solution is the right way, you might want to change the Column Defs page in the docs to not use a column helper and a typed array. That is what you’re saying right, either use one or the other?

We skipped using columnDef, it still works as good and gives type help.

  const columns = [
      columnHelper.accessor("name", {
        cell: (info) => info.getValue(),
      }),
      columnHelper.accessor("age", {
        cell: (info) => info.getValue(),
      }),
    ]

Waiting for the solution to this issue too.

This is the way.

@4ndrs That’s what I did previously, it’s not ideal but it work’s perfectly fine tbh.

This is my demo from what I created a tanstack table at my last role, see this

I wish people would stop spamming this thread 😆 There a good few answers here now, give them a go and see if any of them help you out.

@tannerlinsley and all the other maintainers/typescript wizards have done an incredible job with this library especially after it got a massive upgrade in ❤️ It’s really difficult to get this sort stuff right so I’m sure in this particular case an “any” or “unknown” cast will do the trick everything else works great last time I checked.

I’m going to unsubscribe from this thread as I keep getting emails about it 🤣

@RestartDK

I have been using the any approach when defining my table props:

// table component
type Props<T> = {
  data: T[];
  columns: ColumnDef<T, any>[];
};
// when using the table component

const columnHelper = createColumnHelper<Vehicle>();

const columns = [
  columnHelper.accessor("brand", {
    header: "Marca",
  }),
  columnHelper.accessor("model", {
    header: "Modello",
  }),
]

const Testing = () => {
  const vehicles = useVehicles();

  return (
      <Table data={vehicles} columns={columns} />
  );
};

I haven’t had any issues with inference or missing types so far.

@tanstack/react-table: “^8.15.3”

You should only be using the column helper and not pre-typing anything.

Hello, I am still facing the same issue on 8.15.0 and 8.15.3. I am following the shadcn example (Preview / Code) Can’t make it work with

const columns: ColumnDef<Task, any>[] = [

nor

const columns: ColumnDef<Task>[] = [

I am still getting the following error:

Type 'ColumnDef<Task, any>[]' is not assignable to type 'ColumnDef<unknown, any>[]'.
  Type 'ColumnDef<Task, any>' is not assignable to type 'ColumnDef<unknown, any>'.
    Type 'ColumnDefBase<Task, any> & StringHeaderIdentifier' is not assignable to type 'ColumnDef<unknown, any>'.
      Type 'ColumnDefBase<Task, any> & StringHeaderIdentifier' is not assignable to type 'AccessorFnColumnDefBase<unknown, any> & IdIdentifier<unknown, any>'.
        Property 'accessorFn' is missing in type 'ColumnDefBase<Task, any> & StringHeaderIdentifier' but required in type 'AccessorFnColumnDefBase<unknown, any>'.

The only workaround I use for now is:

columns: columns as ColumnDef<unknown>[],

👀

Yeah… we should fix that. On Oct 5, 2022 at 11:40 AM -0700, Chris Sandvik @.***>, wrote:

@tannerlinsley This is the first example in the Column Defs guide page: // Define your row shape type Person = { firstName: string lastName: string age: number visits: number status: string progress: number }

const columnHelper = createColumnHelper<Person>()

// Make some columns! const defaultColumns: ColumnDef<Person>[] = [ // <- Pre typed Array // Display Column columnHelper.display({ // <- While using column helper id: ‘actions’, cell: props => <RowActions row={props.row} />, }), // Grouping Column columnHelper.group({ header: ‘Name’, footer: props => props.column.id, columns: [ // Accessor Column columnHelper.accessor(‘firstName’, { cell: info => info.getValue(), footer: props => props.column.id, }), // Accessor Column columnHelper.accessor(row => row.lastName, { id: ‘lastName’, cell: info => info.getValue(), header: () => <span>Last Name</span>, footer: props => props.column.id, }), ], }), // … It has the column array pre-typed and throws errors if any of these accessor columns are top level. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

@tannerlinsley This is the first example in the Column Defs guide page:

// Define your row shape
type Person = {
  firstName: string
  lastName: string
  age: number
  visits: number
  status: string
  progress: number
}

const columnHelper = createColumnHelper<Person>()

// Make some columns!
const defaultColumns: ColumnDef<Person>[] = [  // <- Pre typed Array
  // Display Column
  columnHelper.display({ // <- While using column helper
    id: 'actions',
    cell: props => <RowActions row={props.row} />,
  }),
  // Grouping Column
  columnHelper.group({
    header: 'Name',
    footer: props => props.column.id,
    columns: [
      // Accessor Column
      columnHelper.accessor('firstName', {
        cell: info => info.getValue(),
        footer: props => props.column.id,
      }),
      // Accessor Column
      columnHelper.accessor(row => row.lastName, {
        id: 'lastName',
        cell: info => info.getValue(),
        header: () => <span>Last Name</span>,
        footer: props => props.column.id,
      }),
    ],
  }),
  // ...

It has the column array pre-typed and throws errors if any of these accessor columns are top level.

Only way I’ve found to get around this is to add a as string or some other primitive type after info.getValue()