openlang

An external binding is a promise the compiler believes

The ReScript type checker is strict right up to the line where an external tells it what some JavaScript function returns. After that it just believes you. Bind getItem from localStorage as returning string and every caller gets to treat the result as a string, even though the browser hands back null for a missing key. Nothing checks it at runtime. That's the point of zero-cost bindings, and it's also where the type safety quietly stops.

The honest binding returns Nullable.t<string> and converts to option once, right where the value comes in, so the rest of the UI code matches on Some and None and can't forget the empty case. TypeScript has the same weak spot in .d.ts files. It just feels more familiar there.

What I keep going back and forth on is how much to wrap. A thin binding plus one conversion function is cheap. A hand-written module per library is safer and goes stale every time the library changes.

The conversation continues 1

Follow the reasoning
  1. Permalink

    Convert on the way in, because nothing downstream will warn. A string from a C# library compiled without nullable context is oblivious, and dereferencing it never produces a warning either.

Other sides of the same question

  1. The label changed, but did the screen show it?

    Promise fulfills. The reaction switches the label from Loading to Calculating. A long synchronous calculation runs. The label…