Upgrading to 9.1 and calling methods

Hi,

I’m trying to upgrade from 9.0.4 to 9.1, and keep running into errors.

I use the bucklescript-tea library as the basis for my app, and almost all my interactions with it look like this:

type 'node t = <
  preventDefault : unit -> unit [@bs.meth];
> Js.t

let result = event["preventDefault"]()

This was fine in 9.0.4, but in 9.1, I get type errors like this for each of them:

This expression has type Js_OO.Meth.arity0
It is not a function

I can’t find any guidance on how to upgrade to 9.1 with this sort of thing. I’ve listed what I’ve tried in various scenarios below, but would love to read something definitive about what the right way to do this is.

Example 1 - changed the types

In this case, I control the type definitions. I had this before:

type rollbar_mod = {@meth "init": Js.Json.t => unit}
@module external rollbar: rollbar_mod = "rollbar"
...
rollbar["init"](rollbarConfig)

looking through the docs, it seems the new way to do it is like this:

  type rollbar_mod
  @send external init: (rollbar_mod, Js.Json.t) => unit = "init"
  @val external rollbar: rollbar_mod = "rollbar"
  ...
  init(rollbar, rollbarConfig)

So that wasn’t too hard, but also I’m not really sure if I’m doing this right.

Example 2 - got a workaround

The library I’m using has this type definition for JS DOM Events:

type 'node t = <
  target : 'node Js.undefined [@bs.get];
  keyCode : int [@bs.get];
  preventDefault : unit -> unit [@bs.meth];
  stopPropagation : unit -> unit [@bs.meth];
> Js.t

When using methods from this type, I previously called them like this:

      event["stopPropagation"]() |> ignore

However, that code now gives me a type error:

This expression has type Js_OO.Meth.arity0
It is not a function

I couldn’t work this out and ended up doing this:

%raw(`event["preventDefault"]()`)

Example 3 - I’m stuck

I have this type, defined in an external library:

type rect = <
  top : float;
  bottom : float;
  left : float;
  right : float;
> Js.t

type t = <
  getBoundingClientRect : unit -> rect [@bs.meth];
> Js.t

The VSCode plugin tells me it believes this to be:

Web_node.t
type t = {
  "getBoundingClientRect": Js_OO.Meth.arity0<rect>,
}

If I try and call it like this:

  let rect = elem["getBoundingClientRect"]()

I get an error:

This expression has type Js_OO.Meth.arity0<Web_node.rect>
It is not a function.

What am I supposed to do here? (I’ve tried various other things but couldn’t figure this out)

Summary

I can’t find any guidance on how to upgrade to 9.1 when using objects with methods that are defined in a library. I’ve listed what I’ve tried in various scenarios, but would love to read something definitive about what the right way to do this is.

Thanks!

I don’t know if ReScript 9.1 has really broken that method call usage or if there is a simple alternative way to call it–I’m a bit out of the loop. But even if it has broken the usage, you can still work around it by defining your own getter for the existing type:

// Example 3
@send external getBoundingClientRect: t => rect = "getBoundingClientRect"

let rect = elem->getBoundingClientRect

Why does this work? Because t models a JS object, and we can use @send to work with JS objects. It generates the expected output:

x.getBoundingClientRect()
1 Like