Using Dom.Storage in Promises

Hi!

I have the following code:

type authResponse = {
  "access_token": string,
  "expires_in": int,
  "id_token": string,
  "refresh_token": string,
  "scope": string,
  "token_type": string,
}

type auth = {loginUsername: (string, string) => Js.Promise.t<authResponse>}

@module("@patient/data-sdk") external auth: auth = "auth"

auth.loginUsername("foo", "Bar")->Js.Promise.then_(value => {
  Dom_storage.setItem("session", Js.Json.stringify(value), Dom_storage.localStorage)
  
  Js.Promise.resolve(value)
}, _)->ignore

It fails saying that:

 109 ┆ auth.loginUsername(username, password)
  110 ┆ ->Js.Promise.then_(
  111 ┆   value => {

  This has type:
    Js.Promise.t<authResponse> (defined as Js_promise.t<authResponse>)
  Somewhere wanted:
    Js.Promise.t<Js.Json.t> (defined as Js_promise.t<Js.Json.t>)

  The incompatible parts:
    authResponse (defined as
      {
  "access_token": string,
  "expires_in": int,
  "id_token": string,
  "refresh_token": string,
  "scope": string,
  "token_type": string
,})
    vs Js.Json.t (defined as Js_json.t)

Playground link

It seems that using Js.Json.stringify mutates the value, How else can I do this?
I can’t find any information about this or probably don’t know how to look for it.

Any help is deeply apreciated, been trying to fix it for some time and I am very frustrated at this moment. :confused:

1 Like

You need to use stringifyAny, because stringify wants a proper Js.Json.t value.

in your example:

  switch Js.Json.stringifyAny(value) {
  | Some(str) => Dom_storage.setItem("session", str, Dom_storage.localStorage)
  | None => ()
  }

  Js.Promise.resolve(value)

Thank you, I was confusing

This has type:
    Js.Promise.t<authResponse> (defined as Js_promise.t<authResponse>)

with the callback return.

I think it would had help if the error only says authResponse and not the entire Promise type.

I think the first sentence is just the birds eye view, but there is also more context after that:

This has type:
    Js.Promise.t<authResponse> (defined as Js_promise.t<authResponse>)
  Somewhere wanted:
    Js.Promise.t<Js.Json.t> (defined as Js_promise.t<Js.Json.t>)
  
  The incompatible parts:
    authResponse (defined as
      {
  "access_token": string,
  "expires_in": int,
  "id_token": string,
  "refresh_token": string,
  "scope": string,
  "token_type": string
,})
    vs Js.Json.t (defined as Js_json.t)

The last part gave me enough hints to understand what’s wrong

Yeah, but as a newbie, it is hard to catch.

Take for example this error:
image

It is possible to replace unit for Js.Json.t?

The error refers to a type mismatch within your return types… you are not handling the return value of your stringify call.

Here’s a working example:

let str = Js.Json.stringify(value)

which will work fine. If you want to use expressions without explicitly handling the return value, use ignore:

Js.Json.stringify(value)->ignore