Docs / Language Manual / Bind to JS Object
Edit

You are currently looking at the v6.0 - v8.2 docs (Reason v3.6 syntax edition). You can find the latest manual page here.

(These docs are equivalent to the old BuckleScript docs before the ReScript rebrand)

Bind to JS Object

JavaScript objects are a combination of several use-cases:

  • As a "record" or "struct" in other languages (like ReScript and C).

  • As a hash map.

  • As a class.

  • As a module to import/export.

ReScript cleanly separates the binding methods for JS object based on these 4 use-cases. This page documents the first three. Binding to JS module objects is described in the Import from/Export to JS section.

Bind to Record-like JS Objects

Bind Using ReScript Record

If your JavaScript object has fixed fields, then it's conceptually like a ReScript record. Since a ReScript record compiles to a clean JavaScript object, you can definitely type a JS object as a ReScript record!

Reason (Old Syntax)ML (Older Syntax)JS Output
type person = {
  name: string,
  friends: array(string),
  age: int,
};

[@bs.module "MySchool"] external john: person = "john";

let johnName = john.name;

External is documented here. @bs.module is documented here.

Bind Using ReScript Object

Alternatively, you can use ReScript object to model a JS object too:

Reason (Old Syntax)ML (Older Syntax)JS Output
type person = {
  .
  "name": string,
  "friends": array(string),
  "age": int,
};

[@bs.module "MySchool"] external john: person = "john";

let johnName = john##name;

Bind Using Special @bs Getters & Setters

Alternatively, you can use bs.get and bs.set to bind to individual fields of a JS object:

Reason (Old Syntax)ML (Older Syntax)JS Output
type textarea;
[@bs.set] external setName: (textarea, string) => unit = "name";
[@bs.get] external getName: textarea => string = "name";

You can also use bs.get_index and bs.set_index to access a dynamic property or an index:

Reason (Old Syntax)ML (Older Syntax)JS Output
type t;
[@bs.new] external create: int => t = "Int32Array";
[@bs.get_index] external get: (t, int) => int = "";
[@bs.set_index] external set: (t, int, int) => unit = "";

let i32arr = create(3);
i32arr->set(0, 42);
Js.log(i32arr->get(0));

Bind to Hash Map-like JS Object

If your JavaScript object:

  • might or might not add/remove keys

  • contains only values that are of the same type

Then it's not really an object, it's a hash map. Use Js.Dict, which contains operations like get, set, etc. and cleanly compiles to a JavaScript object still.

Bind to a JS Object That's a Class

Use bs.new to emulate e.g. new Date():

Reason (Old Syntax)ML (Older Syntax)JS Output
type t;
[@bs.new] external createDate: unit => t = "Date";

let date = createDate();

You can chain bs.new and bs.module if the JS module you're importing is itself a class:

Reason (Old Syntax)ML (Older Syntax)JS Output
type t;
[@bs.new] [@bs.module] external book: unit => t = "Book";
let myBook = book();