How do you create mutable external value?


Hi there! I would like to create ReasonML bindings for a mapbox-gl package. Mapbox requires an accessToken to be provided before you can use a library. The proper way to provide this token is to set accessToken on mapbox-gl import.

import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = '...';

I’ve created following bindings:

[@bs.module "mapbox-gl"] [@bs.val]
external accessToken: ref(string) = "accessToken";

But then I try to set accessToken with

MapboxGL.accessToken := "...";

I’m getting Uncaught TypeError: Cannot set property '0' of null. Am I missing something?


I often find that looking at the generated javascript is super useful in situations like these. I just ran it through bucklescript and got

var MapboxGl = require("mapbox-gl");

MapboxGl.accessToken[0] = "...";

See, ref's are represented at runtime as an array of length 1, so “setting the contents” of a ref is e.g. theref[0] = 5.

Here’s what I would recommend:

type mapboxGlModule;

external mapboxGl: mapboxGlModule = "mapbox-gl";

external setAccessToken: (mapboxGlModule, string) => unit = "accessToken";

setAccessToken(mapboxGl, "something");

which produces the javascript:

var MapboxGl = require("mapbox-gl");

MapboxGl.accessToken = "something";

/*  Not a pure module */


Oh, wow! Thanks, @jaredly!

I’m still new to ReasonML, where can I find generated javascript for a module? Consider this bsconfig.json:

  "name": "reason-react-mapbox-gl",
  "reason": {
    "react-jsx": 2
  "sources": {
    "dir": "src",
    "subdirs": true
  "package-specs": [
      "module": "es6",
      "in-source": true
  "suffix": ".bs.js",
  "namespace": true,
  "bs-dependencies": ["reason-react"],
  "bsc-flags": ["-bs-super-errors"],
  "refmt": 3
} contains only this


var $$Map = /* module */[];

export {
  $$Map ,
/* No side effect */


Oh, I got it. It was all in the compiled module I use for debug :slight_smile: