Since this is something that comes up from time to time, you can also just add another binding to create
that returns the instance typed as a function directly, that then return t
when invoked:
Excerpt:
module Ky = {
module Instance = {
type options = {method?: string}
type t
type instance = (string, ~options: options=?) => t
@send external get: (t, string) => t = "get"
type createOptions = {prefixUrl: string}
@module("Ky") @scope("Instance")
external createCallable: createOptions => instance = "create"
@module("Ky") @scope("Instance")
external create: createOptions => t = "create"
@send external json: t => JSON.t = "json"
}
}
let kyInstance = Ky.Instance.create({prefixUrl: "someBasePath"})
let kyInstanceCallable = Ky.Instance.createCallable({prefixUrl: "someBasePath"})
let one = kyInstanceCallable("path", ~options={method: "GET"})->Ky.Instance.json
let two = kyInstance->Ky.Instance.get("path")->Ky.Instance.json
Take away: It’s fine (and encouraged) to create several bindings to the same underlying thing, but with different types as needed. Same JS output, and easy to control if you want the callable or not directly.
And finally, here’s an example when there’s just a single create function bound, that can also be called, or invoked via a get
method. This works if you don’t need to return the same type t directly again, and is probably the best given the presented situation: ReScript Playground
Excerpt:
// kyInstance("path", {method: "GET"}).json()
// kyInstance.get("path").json()
module Ky = {
module Instance = {
type options = {method?: string}
type t
type instance = (string, ~options: options=?) => t
@send external get: (instance, string) => t = "get"
type createOptions = {prefixUrl: string}
@module("Ky") @scope("Instance")
external create: createOptions => instance = "create"
@send external json: t => JSON.t = "json"
}
}
let kyInstance = Ky.Instance.create({prefixUrl: "someBasePath"})
let one = kyInstance("path", ~options={method: "GET"})->Ky.Instance.json
let two = kyInstance->Ky.Instance.get("path")->Ky.Instance.json
Produces the expected JS.
Take away: Even if you use the type t
pattern with methods via @send
, type t can be anything. It doesn’t need to be abstract.