tl;dr: How to change the following binding to be able to write Intl.DateTimeFormat.make()
instead of Intl_.DateTimeFormat.make()
?
type dateTimeFormat;
[@bs.deriving abstract]
type formatOptions = {
[@bs.optional]
weekday: string,
[@bs.optional]
day: string,
[@bs.optional]
month: string,
};
module Intl_ {
module DateTimeFormat {
module Impl {
type t;
};
[@bs.new] external make: unit => Impl.t = "Intl.DateTimeFormat";
[@bs.send] external format: (Impl.t, Js.Date.t) => string = "";
};
}
Intl_.DateTimeFormat.make()
->Intl_.DateTimeFormat.format(Js.Date.make())
->Js.log;
The issue
Without the underscore, this would compile to:
var Impl = /* module */[];
var DateTimeFormat = /* module */[/* Impl */Impl];
var Intl = /* module */[/* DateTimeFormat */DateTimeFormat];
console.log(new Intl.DateTimeFormat().format(new Date()));
exports.Intl = Intl;
The issue is that var Intl = ...
shadows the global Intl
, and thus breaks new Intl.DateTimeFormat()
.
First of all, I'd consider this a bug in BuckleScript. This problem was most recently brought up in issue #3268 and partially resolved in this commit, but it still leaves a lot of names unreserved. You should consider bringing this up there or in a new issue.
In the meantime, you can work around this by fully qualifying the name. Intl
isn't actually a global object, but attached to the global object, which in the context of a web page is window
. But since JavaScript will look for names on the global object when it's not found in the local environment, it looks very much like a global name.
So if you change make
to:
[@bs.new] external make: unit => Impl.t = "window.Intl.DateTimeFormat";
it should work fine.