Error: Field value has a type which is less general than the (defined) scoped polymorphic type

I get an error when I try to use a record type, a field of which is defined with a scoped polymorphic type.

Code:

module ColumnDef = {
  type cellProps<'tData, 'cellData> = {getValue: unit => 'cellData}

  type t<'tData> = {
    id: string,
    // The types of accessorFn and cell fields uses a scoped polymorphic type 'cellData: https://rescript-lang.org/docs/manual/latest/scoped-polymorphic-types
    accessorFn: 'cellData. 'tData => 'cellData,
    cell?: 'cellData. cellProps<'tData, 'cellData> => React.element,
    enableSorting?: bool,
  }
}

type t = {
  id: string,
  rank: int,
}

let columnDefs: array<ColumnDef.t<t>> = [
  {
    id: "ID",
    accessorFn: t => t.id,
  },
  {
    id: "Rank",
    accessorFn: t => t.rank,
  },
]

Error:

[E] Line 21, column 16:

This field value has type t => string
  which is less general than 'cellData. 'tData => 'cellData

Link to playground

Can someone help me solve it?

I guess you’re trying to write bindings to TanStack. Unfortunately scoped polymorphic types are fairly limited and almost only work within bindings, they don’t play well when you write functions in ReScript and the compiler tries to infer the type.

Given you likely don’t care about the type 'cellData as long as it is indeed the same in both accessorFn and cell, because I guess the columnDefs will be consumed by JS and not by ReScript, you could just wrap the type inside an unboxed variant:

module ColumnDef = {
  type cellProps<'tData, 'cellData> = {getValue: unit => 'cellData}

  type tRaw<'tData, 'cellData> = {
    id: string,
    accessorFn: 'tData => 'cellData,
    cell?: 'cellData. cellProps<'tData, 'cellData> => React.element,
    enableSorting?: bool,
  }

  @unboxed type rec t<'tData> = ColumnDef(tRaw<'tData, 'cellData>): t<'tData>
}

type t = {
  id: string,
  rank: int,
}

let columnDefs: array<ColumnDef.t<t>> = [
  ColumnDef({
    id: "ID",
    accessorFn: t => t.id,
  }),
  ColumnDef({
    id: "Rank",
    accessorFn: t => t.rank,
  }),
]

see playground link

Does that solve your issue?

I guess you’re trying to write bindings to TanStack.

Yes. The binding work is making me regret my choice.

Your solution works at first sight. I will test it out further when I get time.

I guess the columnDefs will be consumed by JS and not by ReScript,

As far as I remember, one of the Tanstack Table APIs would require me to access columnDef on ReScript side. I think its flexRender. I would have to test how the solution pans out in that case.

1 Like