Docs / Language Manual / Shared Data Types

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)

Shared Data Types

ReScript's built-in values of type string, float, array and a few others have a rather interesting property: they compile to the exact same value in JavaScript!

This means that if you're passing e.g. a ReScript string to the JavaScript side, the JS side can directly use it as a native JS string. It also means that you can import a JS string and pretend it's a native ReScript string.

Unlike most compiled-to-js languages, in ReScript, you don't need to write data converters back and forth for most of our values!

Shared, bidirectionally usable types:

  • String. Backtick strings like `hello $(personName)` (in old ML syntax: {j|hello $(personName)|j}) support interpolation. Normal "hello" strings don't.

  • Float. ReScript floats are JS numbers, vice-versa.

  • Array. In addition to the JS Array API, we provide our own Belt.Array API too.

  • Tuple. Compiles to a JS array. You can treat a fixed-sized, heterogenous JS array as ReScript tuple too.

  • Boolean.

  • Record. Record compiles to JS object. Therefore you can also treat JS objects as records. If they're too dynamic, consider modeling them on the ReScript side as a hashmap/dictionary Js.Dict or a ReScript object.

  • Object. ReScript objects are JavaScript objects, vice-versa.

  • Function. They compile to clean JS functions.

  • Module. ReScript files are considered top-level modules, and are compiled to JS files 1 to 1. Nested modules are compiled to JavaScript objects.

  • Unit. The unit type, which has a single value (), compiles to undefined too. Likewise, you can treat an incoming JS undefined as ().

Types that are slightly different than JS, but that you can still use from JS:

  • Int. Ints are 32-bits! Be careful, you can potentially treat them as JS numbers and vice-versa, but if the number's large, then you better treat JS numbers as floats. For example, we bind to Js.Date using floats.

  • Option. The option type's None value compiles into JS undefined. The Some value, e.g. Some(5), compiles to 5. Likewise, you can treat an incoming JS undefined as None. JS null isn't handled here. If your JS value can be null, use Js.Nullable helpers.

  • Exception.

Non-shared types (aka internal types):

  • Variant. They don't exist in JS.

  • List, which is just a regular variant.

  • Character.

  • Int64.

  • Lazy values.

  • Everything else.

The non-shared types need your manual conversions if you want to export them for JS consumption. For a seamless JS / TypeScript / Flow integration experience, you might want to use genType instead of doing conversions by hand.