I understand that I can use @external
and @unwrap
with polymorphic variants to call into JavaScript APIs that are informally polymorphic, as in the padLeft
example provided in the documentation: Bind to JS Function | ReScript Language Manual. I’m wondering if I can go the other direction: write a rescript function which compiles to a JavaScript function that accepts an informal polymorphic variant?
I’m writing a library that is used primarily by TypeScript/JavaScript users. I’ve written much of the library internals in ReScript and I would like to port everything to ReScript, but the JS API leverages this informal polymorphism so I would need a way to produce that in ReScript.
Specifically, I’m looking to be able to write something like:
type poly = @unwrap [ #N(NodeRepr.t) | #C(float) ]
@genType
let svf = (~key: option<string>=?, ~mode: string="lowpass", fc: poly, xn: poly) => {
switch key {
| Some(k) => NodeRepr.create("svf", {"key": k, "mode": mode}, [fc, xn])
| None => NodeRepr.create("svf", {"mode": mode}, [fc, xn])
}
}
and have it compile to some TypeScript/JavaScript that my users can call that looks like this:
export const svf: (_1:{ readonly key?: string; readonly mode?: string }, _2:NodeRepr_t|number, _3:NodeRepr_t|number) => NodeRepr_t = function (Arg1: any, Arg2: any, Arg3: any, Arg4: any) {
/* Some auto-generated javascript to wrap the informal arg2 and arg3 into a poly variant */
const a2 = typeof Arg2 === 'number' ? { tag: 'C', val: a2} : { tag: 'N', val: a2 };
const a3 = typeof Arg2 === 'number' ? { tag: 'C', val: a3} : { tag: 'N', val: a3 };
const result = Curry._5(
GeneratedBS.svf, Arg1.key, Arg1.mode, a2, a3);
return result
};
Does that make sense? This way I can write in ReScript with formal polymorphic variants, but via @unwrap
(or similar), ship an API to TS/JS users that they’re more familiar with.