I’m loving the [@bs.deriving abstract]
API, but running into some difficulties understanding how to work with both [@bs.optional]
annotations and type parameters. Here’s my use case.
JS API
I am trying to call a JS API that takes a JS object as a config. This object has one required field (url
) and one optional field (fetchOptions
). The optional field, fetchOptions
can be either an object or a function that returns an object. For example:
const client = new Client({
url: "http://localhost:3001"
})
const client = new Client({
url: "http://localhost:3001",
fetchOptions: {
id: 1234
}
});
const client = new Client({
url: "http://localhost:3001",
fetchOptions: () => {
id: 1234
}
});
are all valid use cases for the API. My first attempt at binding this looks like this:
[@bs.deriving abstract]
type clientConfig('fetchOptions) = {
url: string,
[@bs.optional] fetchOptions: 'fetchOptions
};
[@bs.new] [@bs.module "myModule"]
external client : clientConfig('fetchOptions) => client = "Client";
I’m using a type parameter to say, “Allow the user to pass any sort of value in here.” My first question is: How can I restrict fetchOptions
to be either a JS object or a function returning an arbitrary JS object? Would a polymorphic variant be appropriate here?
Part 2
The above more or less works as long as I actually pass fetchOptions
explictly. For example:
let config = clientConfig(
~url="http://localhost:3001",
~fetchOptions={"me": "you"},
()
);
But it fails if I pass just url
. For example:
let config = clientConfig(
~url="http://localhost:3001",
()
);
results in: This expression's type contains type variables that can't be generalized.
This makes sense because I require a type parameter fetchOptions
when calling clientConfig
. However, I still want API users to get the benefit of the [@bs.optional]
annotation. So my question here is: How can I provide the correct type for fetchOptions
(object or function returning object) without passing a type parameter (and therefore maintaining the optional use case)? Is there a better way to do this altogether and I’m just barking up the wrong tree?
Thanks in advance for any help. Bindings make my head spin a bit