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)


ReScript objects are like records, but:

  • No type declaration needed.

  • Structural and more polymorphic, unlike records.

  • Doesn't support updates unless the object comes from the JS side.

  • Doesn't support pattern matching.

Although ReScript records compile to clean JavaScript objects, ReScript objects are a better candidate for emulating/binding to JS objects, as you'll see.

Type Declaration

Optional, unlike for records. The type of an object is inferred from the value, so you never really need to write down is type definition. Nevertheless, here's its type declaration syntax:

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

Visually similar to record type's syntax, with the field names quoted.


To create a new object:

Reason (Old Syntax)ML (Older Syntax)JS Output
let me = {
  "age": 5,
  "name": "Big ReScript"

Note: as said above, unlike for record, this me value does not try to find a conforming type declaration with the field "age" and "name"; rather, the type of me is inferred as {"age": int, "name": string}. This is convenient, but also means this code passes type checking without errors:

Reason (Old Syntax)ML (Older Syntax)JS Output
type person = {
  "age": int

let me = {
  "age": "hello!" // age is a string. No error.

Since the type checker doesn't try to match me with the type person. If you ever want to force an object value to be of a predeclared object type, just annotate the value:

Reason (Old Syntax)ML (Older Syntax)
let me: person = {
  "age": "hello!"

Now the type system will error properly.


Reason (Old Syntax)ML (Older Syntax)JS Output
let age = me##age;


Disallowed unless the object is a binding that comes from the JavaScript side. In that case, use =:

Reason (Old Syntax)ML (Older Syntax)JS Output
type student = {
  [@bs.set] "age": int,
  [@bs.set] "name": string,
[@bs.module "MyJSFile"] external student1: student = "student1";

student1##name = "Mary";

Tips & Tricks

Since objects don't require type declarations, and since ReScript infers all the types for you, you get to very quickly and easily (and dangerously) bind to any JavaScript API. Check the JS output tab:

Reason (Old Syntax)ML (Older Syntax)JS Output
// The type of document is just some random type 'a
// that we won't bother to specify
[@bs.val] external document: 'a = "document";

// call a method
document##addEventListener("mouseup", _event => {

// get a property
let loc = document##location;

// set a property
document##location##href = "";

The external feature and the usage of this trick are also documented in the external section later. It's an excellent way to start writing some ReScript code without worrying about whether bindings to a particular library exists.