@obj deprecated how to deal with variadic polymorphic values

Hello there,

I’m currently writing some bindings for the latest version of @tanstack/react-table and noticed that @obj decorator is deprecated.

This decorator is pretty useful for this library because of it’s API that allow you to get a different data type for each columns :

// In TypeScript
type Person = {
  firstName: string
  age: number
}

let data = [{firstName: "Thomas", age: 31]
let columns = [{
  id: "firstName",
  accessorKey: person => person.firstName
}, {
  id: "age",
  accessorKey: person => person.age
}]

In ReScript, I used @obj to create an abstract type in wich the accessKey returned data type can be infered :

type cell<'value> = {getValue: unit => 'value}

module Column = {
  type t<'tableData>

  @obj
  external make: (
    ~id: string,
    ~accessorFn: 'tableData => 'columnData,
    ~header: unit => React.element=?,
    ~footer: unit => React.element=?,
    ~cell: cell<'columnData> => React.element=?,
  ) => t<'tableData> = ""
}

type tableOptions<'tableData> = {
  data: array<'tableData>,
  columns: array<Column.t<'tableData>>,
  getCoreRowModel: coreRowModel,
}
type tableInstance

@module("@tanstack/react-table")
external useReactTable: tableOptions<'data> => tableInstance = "useReactTable"

And the usage would be :

type person = {
  firstName: string,
  age: int,
}

let data = [{age: 1, firstName: "toto"}]

useReactTable({
  data,
  columns: [
    Column.make(
      ~id="age",
      ~accessorFn=test => test.age,
      ~cell={
        cell => {
          <p> {cell.getValue()->React.int} </p>
        }
      },
    ),
    Column.make(~id="firstName", ~accessorFn=test => test.firstName),
  ],
  getCoreRowModel: getCoreRowModel(),
})->Js.log

Maybe is there a better way to handle this correctly ?

I guess you could do something like this:

@unboxed
type rec column<'tableData> =
  | Column({
      id: string,
      accessorFn: 'tableData => 'columnData,
      header?: unit => React.element,
      footer?: unit => React.element,
      cell?: cell<'columnData> => React.element,
    }): column<'tableData>

Usage would be:

useReactTable({
  data,
  columns: [
    Column({
      id:"age",
      accessorFn:test => test.age,
      cell: cell => {
          <p> {cell.getValue()->React.int} </p>
        },
    }),
    Column({id:"firstName", accessorFn:test => test.firstName}),
  ],
  getCoreRowModel: getCoreRowModel(),
})->Js.log

But I agree with you, you could arguably defend that @obj still has some valid use cases.