Checking for null/undefined

Hello, I’m working on bindings to a JS library and it’s going well and compiling to what I would type in JS. I have an object method that takes a callback that I have typed as type callback = (. Js.nullable<Js.Exn.t>, Js.nullable<t>) => unit, which I adapted a bit from another answer on here. I’m going for an uncurried function that takes an error and the data; both could presumably (mutually exclusively) be undefined or null, or their respective value. Now I need to use it to send a callback function to the JS side. How should I test for the presence of err? I see there is a isNullable function that returns true if the value is null/undefined and a test (no description) that I guess returns false on null/undefined; should I switch on that result? Something else? Thank you!

You can use Js.Nullable | ReScript API to convert it to an option value, then switch on it like a normal option e.g. Some/None.

EDIT: if you use this style a lot you can write a little wrapper to convert the Node callback style into a more type-safe result style:

let nodeback = (f) => (. err, result) =>
  switch (Js.Nullable.toOption(err), Js.Nullable.toOption(result)) {
  | (Some(err), _) => f(Error(err))
  | (_, Some(result)) => f(Ok(result))
  // Throw if APIs break nodeback 'guarantee':
  | _ => invalid_arg("Nodeback arguments invalid")
  }

Then,

fetchData(nodeback(result =>
  switch result {
  | Ok(value) => ...
  | Error(ex) => ...
  }))
2 Likes

Ok thank you. Another parameter of this object method is array of myType, but null can also be passed in. I typed it in my external for the method as Js.null<array<myType>> because the API docs say “nullable, value of this type can be either null or 'a”, which sounds like what I want. However, when I call the method and pass in an array of myType like [myValue], it won’t compile. It says “This has type: array<'a> Somewhere wanted: Js.null<array<myType>>”. So I am misunderstanding something. I’m not sure I will even need to pass in nulls, I just wanted to create the most robust and flexible binding to the method. Is that the right approach? How can I fix?

I changed the type in my external to Js.Nullable.t<array<myType>> and then at the call site I used Js.Nullable.return([myValue]) and that is compiling, is that right? I haven’t tried it in the browser yet though.

1 Like

Yes, that’s exactly what I was going to suggest.

Awesome, thank you so much!

1 Like