Signature type and chaining promise that resolve with no argument

I have js binding with a function that resolve with no argument. For example:

liff.init({..}).then(() => console.log("intialized")

My question is how do I signature external function to return a promise like code above. Currently, I used unit type but compiler always complain about usage of Js.Promise.then_.

This is my type signature:

// Liff.res
external init: initConfig => Js.Promise.t<unit> = "init"

And here is my usage:

let main = {
    liffId: "ab2d",
  })->Js.Promise.then_(() => Js.Promise.resolve())

The compiler complained:

>>>> Start compiling
bsb: [3/3] src/Main.cmj
FAILED: src/Main.cmj

  We've found a bug for you!

  4 │
  5 │ let main = {
  6 │   Liff.init({
  7 │     liffId: "ab2d",
  8 │   })->Js.Promise.then_(() => Js.Promise.resolve())
  9 │ }

  This has type: Js.Promise.t<unit> (defined as Js_promise.t<unit>)
  Somewhere wanted: 'a => Js.Promise.t<'b>


You need to define the _ placeholder on the last position of Js.Promise.then_, since it’s still a pipe-last API (subject to change soon). To fix your bug you need to do this:

let main = {
    liffId: "ab2d",
  })->Js.Promise.then_(_ => Js.Promise.resolve(), _)

Note the very last _ in the then_ call. This is equivalent to this:

let main = {
  let p = init({
    liffId: "ab2d",

  Js.Promise.then_(_ => Js.Promise.resolve(), p)

@ryyppy Thanks! I didn’t see it has a second argument.

ince it’s still a pipe-last API (subject to change soon)

I might a bit confuse about pipe first and pipe last. How do I know which one use pipe last?

Easiest would be to look at the type-signature, e.g. here it takes a function as the first argument, while the last argument is the Js.Promise.t('a). So you’d use it like:

Js.Promise.then_(Js.Promise.resolve, somePromise)

or with pipe-last:

somePromise |> Js.Promise.then_(Js.Promise.resolve)

…or pipe-first:

somePromise->Js.Promise.then_(Js.Promise.resolve, _)


@lessp Now I understand it. Thanks. :slight_smile: