@unwrap in @react.component

Does anyone have a good example of using @unwrap at a component interface?
Seems like you have to drop the other decorators and do your component module manually?

At a broader view I would love to see @unwrap be more widely supported, I am working with highcharts, for example, which takes a huge options object prop where many many deep inner values are polymorphic, and it seems nearly impossible now to specify that each of those be unwrapped.

…or can i just @unwrap on a object containing variants and it will work? surely not.

Thanks
Alex

2 Likes

Hi @mouton did you have any success with this?

Not sure if this will help, but I’ll offer a few thoughts.

I’m assuming you would like to do something like the Highcharts React example (but presumably a more complex version):

const options = {
  title: {
    text: 'My chart'
  },
  series: [{
    data: [1, 2, 3]
  }]
}

const App = () => (
  <div>
    <HighchartsReact
      highcharts={Highcharts}
      options={options}
    />
  </div>
);

The first option that you might have already considered is to use a ReScript object:

let options = {
  "title": {
    "text": "My chart",
  },
  "series": [
    {
      "data": [1, 2, 3],
    },
  ],
}

Which produces:

var options = {
  title: {
    text: "My chart",
  },
  series: [
    {
      data: [1, 2, 3],
    },
  ],
};

We don’t get type safety here, but it’s simple and might be a good option if your risk of errors is low.

Another option may be to use the @obj decorator:

module Options = {
  type t
  type title
  type series

  @obj external title: (~text: string) => title = ""

  @obj external series: (~data: array<int>) => series = ""

  @obj external make: (~title: title=?, ~series: array<series>=?) => t = ""
}

let options = Options.make(
  ~title=Options.title(~text="My chart"),
  ~series=[Options.series(~data=[1, 2, 3])],
)

Which produces the same:

var options = {
  title: {
    text: "My chart",
  },
  series: [
    {
      data: [1, 2, 3],
    },
  ],
};

I tried using @unwrap with @react.component but I wasn’t able to get that working.

Also see this previous post by @tsnobip which also described a similar problem.

Edit: You mentioned some of the options are polymorphic. Do you have an example of one of those options?

2 Likes

thanks kevan for the incredibly thoughtful response

The series data in your example would be polymorphic.
type series<'val> = { data: array<'val> }

an object would of course work but the highcharts api is ~20k lines in rescript with type parameters [and recursive types!] at many levels and is really the place where you want types, no? I cant remember all that.

we tried @obj but again the obj constructors produce objects which again drop typing, so it prevents you from integrating those values into the broader options structure in a typed way.

@deriving(abstract) has worked pretty well for creating objects especially since these are being sent into
js and never(?) return, but this leaves us with the type parameters bubbling up and im guessing @unwrap doesnt work on a @deriving(abstract) [but i would like to be wrong]

I think our approach will be to use opaque types instead of parameterized for each inner thing, leaving the top level options type unparameterized.and then we may be able to use @unwrap in those constructors since they will be external … = “%identity” and that might work?

Thanks
A

1 Like

an object would of course work but the highcharts api is ~20k lines in rescript with type parameters [and recursive types!] at many levels and is really the place where you want types, no? I cant remember all that.

It’s a good question. It sounds like a cost/benefit situation. Some questions I ask myself include; How much of an API do I need. How often is that code changing? What are the risks of there being a mistake with no-one noticing. I’m sure you’ve already weighed up pros and cons for your case.

I think our approach will be to use opaque types instead of parameterized for each inner thing, leaving the top level options type unparameterized.and then we may be able to use @unwrap in those constructors since they will be external … = “%identity” and that might work?

I believe that @unwrap is currently only supported for regular externals, and not %identity.

But opaque types sounds like a great option. All the best getting this working nicely.