Type annotation of a variadic function

Hi folks! I need help writing a type that annotates a Javascript variadic function. Maybe this is the wrong angle, so any suggestion is welcomed.

I’m currently writing some bindings for Bun’s SQL API. The SQL constructor returns a function (with some properties, like begin or unsafe) that can be interfaced using a template literal. Like this:

const sqlite = new SQL("sqlite://myapp.db");
const sqliteResults = await sqlite`
  SELECT * FROM users 
  WHERE active = ${1}
`;

await sqlite.begin(async tx => {
  await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
});

So my bindings look like this:

@variadic // <--- I need T to be variadic
type t = (array<string>, array<'a>) => 'b

@module("bun") @new
external make: string => t = "SQL"

type sqlTransactionContextCallback = t => 'a

@send
external begin: (t, sqlTransactionContextCallback) => promise<'a> = "begin"

But that unfortunately doesn’t actually work :frowning: (playground)

Currently I have in mind cheating and adding a wrapper function that destrucutures the parameters array in raw js (playground), but I would rather avoid that if possible.

Edit:
Something I forgot to add is that I want the variadic, or the wrapper if need be, so that the DX is as close as possible to JS; with template literals.

Will this work?

module SQLQuery = {
  type t<'a> = promise<'a>
}

@unboxed
type rec param = Boolean(bool)

type t
type t_query = (array<string>, array<param>) => SQLQuery.t<param>

@module("bun") @new
external make: string => t = "SQL"
external toQuery: t => t_query = "%identity"

@send
external begin: (t, t_query => 'a) => 'a = "begin"

let run = async () => {
  let sqlite = make("sqlite://myapp.db")

  let query_sqlite = toQuery(sqlite)
  let sqliteResults =
    await query_sqlite`
  SELECT * FROM users 
  WHERE active = ${Boolean(true)}
`

  let begin_results = begin(sqlite, async tx =>
    await tx`
  SELECT * FROM users 
  WHERE active = ${Boolean(true)}
`
  )

  Js.log((sqliteResults, begin_results))
}

Playground link

1 Like

Thanks! But that doesn’t work because you loose the variadic output:

You suggestion outputs:

tx(["strings", "string"], ["param1", "param2"]) // <- params as one array

But it needs to output:

tx(["strings, "string"], "param1", "param2") // <- params array spread out

Yeah unfortunately we don’t support this yet ! I’d love to fix this at some point. Don’t hesitate to take a stab at it if you’re motivated :slight_smile:

3 Likes