table icon indicating copy to clipboard operation
table copied to clipboard

ColumnDef types gives typescript error

Open Jontii opened this issue 2 years ago • 51 comments

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

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

  • [X] I agree to follow this project's Code of Conduct
  • [X] 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.

Jontii avatar Sep 15 '22 08:09 Jontii

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

byroncoetsee avatar Sep 17 '22 15:09 byroncoetsee

I'm having the same problem, any updates on this?

j-fdion avatar Sep 26 '22 17:09 j-fdion

I m having same, so i fix with

const columns = useMemo<ColumnDef<Example, any>[]>

i don't know if this is the best way, but the typescript error should go away.

phongplus avatar Sep 27 '22 03:09 phongplus

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(),
      }),
    ]

Jontii avatar Sep 29 '22 08:09 Jontii

This is the way.

tannerlinsley avatar Sep 29 '22 20:09 tannerlinsley

Thank you, it does work this way!

j-fdion avatar Sep 30 '22 14:09 j-fdion

@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?

csandman avatar Oct 04 '22 22:10 csandman

If I understand it, if you use grouped columns like this example https://tanstack.com/table/v8/docs/examples/react/column-sizing then it is correct. If you are not using grouped columns, you shouldn't use it.

Jontii avatar Oct 05 '22 09:10 Jontii

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

tannerlinsley avatar Oct 05 '22 17:10 tannerlinsley

@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.

csandman avatar Oct 05 '22 18:10 csandman

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: () => Last Name, 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 avatar Oct 05 '22 23:10 tannerlinsley

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.

swernerx avatar Oct 18 '22 11:10 swernerx

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.

invalidBan avatar Oct 20 '22 07:10 invalidBan

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.

This makes typescript happy IF you allow use of any which my codebase explicitly does not and which TS does not recommend

jonahallibone avatar Nov 02 '22 21:11 jonahallibone

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

skuridin avatar Nov 22 '22 22:11 skuridin

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

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

LoicKairon avatar Feb 07 '23 08:02 LoicKairon

The EditableData example also uses React.useMemo<ColumnDef<Person>[]>(, I guess that's not correct either?

IanVS avatar Feb 24 '23 15:02 IanVS

@LoicKairon Glad I'm not the only one having this issue, I've done the same as you for now but would but nice to get that work properly.

AlexMachin1997 avatar May 12 '23 14:05 AlexMachin1997

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>[];
};

Patriksafar avatar Jun 01 '23 08:06 Patriksafar

I just encountered the same issue, which forced me to turn off no-explicit-any.

Armadillidiid avatar Aug 28 '23 15:08 Armadillidiid

Same use case as above, useTable is wrapped in a reuseable component that takes in columns as a prop. Trying to use columHelper to create the definitions in the parent and it causes a typescript error.

DoubleJ-G avatar Sep 26 '23 12:09 DoubleJ-G

Any update on this issue? Running into the same issue. My solution is to use any for the type and individually define the types for each cell:

type BillingDetails = {
  id: number;
  service: string;
  talentName: string;
  amount: number;
  createdAt: string;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any 
const columns: ColumnDef<BillingDetails, any>[] = [
  columnHelper.accessor('service', {
    id: 'service',
    cell: (props) => props.getValue() as string,
    header: 'Service',
    enableSorting: false,
  }),
  columnHelper.accessor('talentName', {
    id: 'talentName',
    cell: (props) => props.getValue() as string,
    header: 'Talent name',
    enableSorting: false,
  }),
  columnHelper.accessor('amount', {
    id: 'amount',
    cell: (props) => props.getValue() as number,
    header: 'Amount',
    enableSorting: false,
  }),
  columnHelper.accessor('createdAt', {
    id: 'createdAt',
    cell: (props) => props.getValue() as string,
    header: 'Created at',
    enableSorting: false,
  }),
]

blumaa avatar Oct 09 '23 09:10 blumaa

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

cameronthrntn avatar Nov 08 '23 12:11 cameronthrntn

Yeah getting same issue.

arkmech avatar Nov 25 '23 15:11 arkmech

is there any solution for this. this still exists.

suresh-laradev avatar Dec 09 '23 05:12 suresh-laradev

Waiting for the solution to this issue too.

ngurahyudi avatar Dec 10 '23 07:12 ngurahyudi

yeah please i really require a solution for this.

Ac-Srikanth avatar Dec 12 '23 12:12 Ac-Srikanth

Any progress here? Going to have to drop react-table if this isn't fixed, unfortunately.

PeterEckIII avatar Dec 14 '23 21:12 PeterEckIII

Any progress here? Going to have to drop react-table if this isn't fixed, unfortunately.

That's very excessive, just put any for the second argument and it'll still work really well.

AlexMachin1997 avatar Dec 15 '23 08:12 AlexMachin1997

Can anyone provide a working vue-table example project that passes column info into a table component? I'm using typescript and getting the following error no matter how I move the types around: Uncaught (in promise) TypeError: columnDefs2 is undefined

Edit: An example that works even with the any type would be awesome, I can't even get that to work.

fs-swhittle avatar Jan 05 '24 17:01 fs-swhittle