1    declare interface Person {
2      name: string;
3      age: number;
4      displayName(): string;
5    }
6
7    declare var ryan: Person;
8
9
10
11
12                                 
1    module Person = {
2      [@bs.deriving abstract]
3      type t = {
4        name: string,
5        age: float,
6      };
7      [@bs.send]
8      external displayName :
9        (t, unit) => string = "";
10    };
11   [@bs.val]
12   external ryan : Person.t = "";

What & Why

ReasonML is a solid language by itself, and BuckleScript is a fantastic compiler. However interop is needed, and one of the most confusing parts of writing ReasonML is writing bindings to JS globals and npm libraries. With BuckleScript, those bindings are written as part of the code itself. It's a really flexable system and aligns closely with OCaml's C interop, but it can be a huge point of confusion for newcomers. One of the main reasons behind this is that there's little direction on where to go for some common JS idioms, like classes, interfaces, and functions that can take different types of arguments. The tools are there, but they are difficult to discover and it takes time to learn how to bind to various JS constructs.

There's a few JS type systems out there, like Flow and TypeScript, that offer a more declarative way of introducing JS constructs into their type system. The easy part for them is that they don't have to add a runtime or make those JS constructs idiomatic, because they're type systems on top of JS! But those type systems have a ton of types written for them (especially TypeScript) because they're stright-forward to write for a lot of the JS community.

Dre is a new approach to giving Reason developers easy access to writing bindings like they do in other ecosystems. Dre reuses Flow's syntax to provide an approachable interface that looks like JavaScript, but under the hood uses Reason's type system instead of Flow's. The JS syntax that Dre uses is compiled to idiomatic Reason bindings for the JS structures declared in a Dre file.

Introduction

Dre files

All Dre code in written in files ending in .dre. These "dre" files are then compiled to Reason using the reason-dre command-line compiler.

Getting Started

Installation

Installing the CLI is easy. To install with npm, run npm install -g reason-dre. Note that a global compiler is recommended, to sit next to BSB, BuckleScript's build system.

BSB Integration

BSB has hooks called "generators" that can be used to automatically compile Dre Files to Reason code. The Dre CLI works really well with this integration, and in the future will support automatically generating this part of your BuckleScript configuration for you.

First, register Dre with BuckleScript: // bsconfig.json { "name": "my-project", "generators": [{ "name": "dre", "command": "reason-dre $in" }] } This should set up Dre for being used as a generator for Reason files in BuckleScript!. The next step is to set up individual files for compilation with Dre: // bsconfig.json { "name": "my-project", "generators": ... "sources": [ { "dir": "bindings", "generators": [ { "name": "dre", "edge": ["MyBinding.dre", ":", "MyBinding.re"] } ] } ] } Note that you need to create a new entry in generators for every Dre file you create, and if you create a Dre file outside of the bindings directory we just set up, you need to register generators in that directory too. For this reason we recommend keeping all Dre files in your project in a directory named bindings.

Binding to JavaScript types

Basic Types

Number declare var someNumber: number;
String declare var someString: string;