Struggling converting from Js object to reasonml record in nextjs getInitialProps


#1

So I’m just trying to get started with reason and I’m getting into a bit of a pickle. I’m trying to adapt the with-reasonml example from nextjs to see if I can read a query item from the url

[@react.component]
let make = (~slug) => {
  <div>
    <Header />
    <p> {ReasonReact.string("HOME PAGE is here!")} </p>
    <p> {ReasonReact.string("id: " ++ slug)} </p>
    <Counter />
  </div>;
};

type query = {slug: string};

let default = make;

let getInitialProps = context =>
  Js.Promise.make((~resolve, ~reject as _) => {
    let slug =
      switch (Js.Nullable.toOption(context##query##slug)) {
      | None => "None"
      | Some(slug) => slug
      };
    resolve(. {"slug": slug});
  });

let inject:
  (
    Js.t('a) => React.element,
    {. "query": Js.Nullable.t(Js.t('a))} => Js.Promise.t(Js.t('a))
  ) =>
  unit = [%bs.raw
  {| (cls, fn) => cls.getInitialProps = fn |}
];

inject(default, getInitialProps);

I get the following error:

 We've found a bug for you!
  /Code/research/with-reasonml-app/pages/index.re 34:17-31

  32 │ ];
  33 │
  34 │ inject(default, getInitialProps);

  This has type:
    {.. "query": Js.t(({.. slug: Js.Nullable.t(string)} as 'a))} =>
    Js.Promise.t({. "slug": string})
  But somewhere wanted:
    {. "query": Js.Nullable.t({. "slug": string})} =>
    Js.Promise.t({. "slug": string})

  The incompatible parts:
    Js.t('a)
    vs
    Js.Nullable.t({. "slug": string}) (defined as
      Js.nullable({. "slug": string}))
  Types for method query are incompatible

I’m not quite sure how I should convert from the option type back to a string?


#2

Your code would not work because your input and ouput weren’t a 1 on 1 match. (one has Js.Nullable.t(string), and the other one is just a string)

let getInitialProps = context =>
  Js.Promise.make((~resolve, ~reject as _) => {
    let slug =
      switch (Js.Nullable.toOption(context##query##slug)) {
      | None => "None"
      | Some(slug) => slug
      };
    resolve(. {"slug": slug});
  });

let inject:
  (
    Js.t('a) => React.element,
    {. "query": {. "slug": Js.Nullable.t(string)}} =>
    Js.Promise.t({. "slug": string})
  ) =>
  unit = [%bs.raw
  {| (cls, fn) => cls.getInitialProps = fn |}
];