Docs / BuckleScript / InteropCheatsheet

Interop Cheatsheet

The next few sections will cover these in detail. Feel free to skip this one if nothing makes sense yet!

Raw JS

RE
let add = [%raw "a + b"]; [%%raw "var a = 1"];

String Unicode & Interpolation

RE
Js.log({js|你好, 世界|js}); let world = "world"; let helloWorld = {j|hello, $world|j};

Global Value

RE
[@bs.val] external setTimeout : (unit => unit, int) => float = "setTimeout";

Global Module

RE
[@bs.val] [@bs.scope "Math"] external random : unit => float = "random"; let someNumber = random(); [@bs.val] [@bs.scope ("window", "location", "ancestorOrigins")] external length : int = "length";

Nullable

RE
let a = Some(5); /* compiles to 5 */ let b = None; /* compiles to undefined */

Handling a value that can be undefined and null, by ditching the option type and using Js.Nullable.t:

RE
let jsNull = Js.Nullable.null; let jsUndefined = Js.Nullable.undefined; let result1: Js.Nullable.t(string) = Js.Nullable.return("hello"); let result2: Js.Nullable.t(int) = Js.Nullable.fromOption(Some(10)); let result3: option(int) = Js.Nullable.toOption(Js.Nullable.return(10));

Object

Records as Objects

Since BuckleScript 7 (preferred for JS object interop)

RE
type action = { [@bs.as "type"] type_: string, username: string }; [@bs.module "actions/addUser.js"] external createAddUser: string => action = "addUser"; let myAction = createAddUser("reason");

Hash Map Mode

RE
let myMap = Js.Dict.empty(); Js.Dict.set(myMap, "Allison", 10);

Abstract Record Mode

RE
[@bs.deriving abstract] type person = { [@bs.optional] name: string, age: int, mutable job: string, }; [@bs.send] external getNickname : person => string = "getNickname"; [@bs.val] external john : person = "john"; let age = john->ageGet; john->jobSet("Accountant"); let nick = john->getNickname;

New Instance

RE
type t; [@bs.new] external createDate : unit => t = "Date";

Function

Object Method & Chaining

RE
[@bs.send] external map : (array('a), 'a => 'b) => array('b) = "map"; [@bs.send] external filter : (array('a), 'a => 'b) => array('b) = "filter"; /* 2, 4 */ [|1, 2, 3|] ->map(a => a + 1) ->filter(a => a mod 2 == 0) ->Js.log;

Variadic (was bs.splice prior to version 4.08)

RE
[@bs.module "path"] [@bs.variadic] external join : array(string) => string = "join";

Polymorphic Function

RE
[@bs.module "Drawing"] external drawCat : unit => unit = "draw"; [@bs.module "Drawing"] external drawDog : (~giveName: string) => unit = "draw";
RE
[@bs.val] external padLeft : ( string, [@bs.unwrap] [ | `Str(string) | `Int(int) ] ) => string = "padLeft"; padLeft("Hello World", `Int(4));

Curry/Uncurry

RE
let add = [@bs] ((x, y, z) => x + y + z); let six = [@bs] add(1, 2, 3);

Module

RE
[@bs.module "path"] external dirname : string => string = "dirname";

Import module.exports

RE
[@bs.module] external simpleFunction : string => string = "simple-module-that-is-a-function";

Import Default

It's important to note that you are not providing the module path to bs.module, but instead as the last argument of external.

RE
[@bs.module] external leftPad : (string, int) => string = "./leftPad";

Import ES6 default compiled from Babel:

RE
[@bs.module "./student"] external studentName : string = "default";

Export ES6 default

RE
let default = "Bob";

Identity External

Final escape hatch converter. Do not abuse.

RE
external myShadyConversion : foo => bar = "%identity";

You can find more examples for the various bs.* attributes here.