I’m trying to use a function that takes a string | number | bool
and want GenType to validate my bindings are correct. But it sure seems to be a lot of work. The ReScript documentation talks about @unwrap
helping with this kind of thing but I couldn’t figure it out. I read somewhere that one great thing about ReScript is that polymorphic variants can get passed to JS without writing any converters. But I can’t get any of it to work. Here is the best I can do. Is there a simpler way? The library I’m binding to has LOTS of weird parameters - string | int
, string | string[]
- and writing all this kind of code for every such parameter is a pain.
Here is a function I want to bind to in a file variantExperiment.ts
…
export type Sizing = "inherit" | number | boolean;
export const logSizing = (i: Sizing) => console.log(i);
This is the simplest ReScript I could figure out…
module Sizing = {
@genType.import(("./variantExperiment", "Sizing"))
type t
external toSizing: 'a => t = "%identity"
let inherit = "inherit"->toSizing
let fromInt = (i: int) => i->toSizing
let fromBool = (i: bool) => i->toSizing
}
@genType.import("./variantExperiment")
external logSizing: Sizing.t => unit = "logSizing"
The generated javascript has this, when what I really want is a zero-cost casting.
function fromInt(i) {
return i;
}
function fromBool(i) {
return i;
}
I don’t think you need genType to bind to this function. Just bind to it as if it were a JavaScript function, but with type information known beforehand:
module Sizing: {
type t
@inline("inherit") let inherit: t
external number: float => t = "%identity"
external boolean: bool => t = "%identity"
} = {
type t = string // This is a white lie because we control the module
@inline let inherit = "inherit"
external number: float => t = "%identity"
external boolean: bool => t = "%identity"
}
@module("./variantExperiment")
external logSizing: Sizing.t => unit = "logSizing"
let () = logSizing(Sizing.inherit)
Rule of thumb: let
bindings generate code, external
s don’t. In this case though ReScript seems to be generating a wrapper for logSizing
even though it’s an external
. Bug perhaps.
Ok I see how external
eliminates any code from the "%identity"
scenario. I prefer to use GenType since it validates I’m using the right parameters; it’s almost no extra code compared to what you proposed except for the defining and importing the type. I still don’t understand why unwrap
doesn’t work with any of this; isn’t it supposed to?
==
Actually, this comes closer but doesn’t work with gentype. The trick was to use a unit () parameter for one of the polymorphic types to get it to compile but I really want a constant string for that one; @unwrap requires payloads on all of them.
@module("./variantExperiment")
external logSizing: @unwrap [#inherit(unit) | #Num(int) | #Bool(bool)] => unit = "logSizing"