When using bs.val how to deal with undefined?


#1

[@bs.val] external envPort: string = “process.env.PORT”

How do I test if envPort is undefined?

Normally I would do const PORT = process.env.PORT || 9000 but that doesn’t work in ReasonML

I know I can also use https://bucklescript.github.io/bucklescript/api/Node.Process.html but the problem is more how one would do it if they had to. And right now if you google it, there is no good results.

https://www.google.com/search?q=process.env.PORT+reasonml
https://www.google.com/search?q=process.env+reasonml


EDIT: An example of how to get a port if defined.

let port = switch(Js.Dict.get(Node.Process.process##env, "PORT")) {
  | Some(string) => string
  | None => "9000"
};

#2

This is how I usually bind to nullable global vars:

[@bs.val][@bs.scope "process.env"] external port: Js.Null_undefined.t(int) = "PORT";
let port: option(int) = Js.Null_undefined.toOption(someVar);

With a default option it can be:

[@bs.val][@bs.scope "process.env"] external port: Js.Null_undefined.t(int) = "PORT";
let port: int = port->Js.Null_undefined.toOption->Belt.Option.getWithDefault(9000);

If you want to avoid the implicit coercion then you just use string instead of int and then use your favorite type conversion method to parse the the int


#3

Thank you, that is really useful, thank you @scull7

I got this to compile, but can’t figure out if it is still wrong?

[@bs.val] external envPort: option(string) = "process.env.PORT"

let port = switch(envPort) {
  | Some(string) => string
  | None => "9000"
}

#4

looks like your code compiles down to:

var match = process.env.PORT;
var port = match !== undefined ? match : "9000";

So if you’re confident about process.env being an object then it should be ok.

Heres my scratch pad:


#5

Your binding looks fine. Note that BuckleScript already provides bindings for some Node things, e.g. https://bucklescript.github.io/bucklescript/api/Node.Process.html

let port = "PORT"
  |> Js.Dict.get(Node.Process.process##env)
  |> Js.Option.getWithDefault("9000");

Really a matter of your preference, whether to write your own specialized bindings or stick with the provided bindings.


#6

@scull7 Thank you, awesome!

@yawaramin Yeah I found that, I posted it later in the original post, took me a bit to understand Js.Dict.get

Looks pretty great with getWithDefault :+1:


I hope that other people can find this thread now :smiley:


Reading Env Variables with Reason and/or Reason-Scripts