How to bind to a function that returns a class

A friend stumped me. He’s using a Javascript library that has some sort of strategy pattern where a function returns a class depending on (I dunno what :man_shrugging:t3:). I can’t find any way (other than using %%raw to make a saner API) to stick an @new on a class that is returned by another function.

Example JS code:

class Foo {
  bar() {
      console.log("bar called")
    }
 }

 function getFoo() {
    // returns a class, how silly
    return Foo
  }

// how to model this is rescript?
  new (getFoo())().bar()

I don’t want to admit that %%raw is the only solution here. :smiley: Any thoughts?

For completeness, here is a link to the %%raw solution.

This is actually a more general issue, how do you bind to the result of a function, it can be a class, a variadic function or a tagged template. I don’t think rescript support this for the time being, but it’d be cool to come up with a solution.

You might need a little JS file to create the class that you can then bind to.

I don’t know what you need this for…

// Set up the condition in JS
%%raw(`
class Foo {
  bar() {
      console.log("bar called")
    }
 }

 function getFoo() {
    return Foo
  }
`)

module type Foo = {
  type t
}
module FooInterface = {
  external getFooClass: unit => module(Foo) = "getFoo"
  external make: module(Foo) => module(Foo) = "new" 
  @send external bar: module(Foo) => unit = "bar"
}

let foo = FooInterface.getFooClass()->FooInterface.make
foo->FooInterface.bar

A little operator priority problem here. Just use new as the name :sweat_smile:

To add constraints from the interface you can

module FooInterface = {
  type t
  external getFooClass: unit => module(Foo with type t = t) = "getFoo"
  external make: module(Foo with type t = t) => module(Foo with type t = t) = "new" 
  @send external bar: module(Foo with type t = t) => unit = "bar"
}

Ok this looks better

module type Foo = {
  type t
}
external getFooClass: unit => module(Foo) = "getFoo"

module FooInterface = {
  type t
  external make: module(Foo) => module(Foo with type t = t) = "new" 
  @send external bar: module(Foo with type t = t) => unit = "bar"
}

let foo = getFooClass()->FooInterface.make
foo->FooInterface.bar
2 Likes