Mar 4, 2024

ReScript 11.1

Unleashing ReScript from React

ReScript Team
Core Development

A couple of weeks ago, the ReScript team released ReScript 11.0, which laid ground work for a lot of possible improvements to make it easier to interact with the JavaScript ecosystem.

This next minor has some wonderful additions to the ReScript toolbelt for you today.

To install, use your favorite package manager to install the new compiler release, e.g.:

SH
npm install rescript@11.1

Find a list of all the new features below:

JSX for more than React

Historically, ReScript has focused mainly on React for its frontend support. This has led to ReScript having a great JSX transform built into the language itself. However, that JSX transform has been quite difficult to use with anything but React.

With v11.1, that changes! The JSX transform can now be configured to work with any framework. First class React support is of course still the same, and remains a priority. This makes it possible to integrate any other framework's JSX idiomatically in ReScript. And, all the tooling like autocompletion of prop names and types just works.

Many popular frameworks like Vue and Preact use JSX. But, JSX is also becoming more and more ubiquitous, and these days JSX can also be used for everything from building CLI apps to responsive e-mail templating. We're happy that ReScript users will now be able to leverage all of these innovations in a more idiomatic way than before.

Here's an example of what a Preact integration could look like:

RESCRIPT
// Greet.res // @jsx.component works the same as @react.component does in React @jsx.component let make = (~name) => { <div> {Preact.string("Hello " ++ name)} </div> }

Read more in the new documentation on the generic JSX transform.

Tagged template literals

This release comes with support for tagged templates.

A tag function in JavaScript is a function that expects an array of strings and variadic parameters as input. Now it's possibe to bind to such functions with the new @taggedTemplate decorator:

ReScriptJS Output
// see https://bun.sh/docs/runtime/shell
type result = {exitCode: int}
@module("bun") @taggedTemplate
external sh: (array<string>, array<string>) => promise<result> = "$"

let filename = "index.res"
let result = await sh`ls ${filename}`

Of course you can also create your own tag functions in ReScript now as well, it is just a function with the following signature.

RESCRIPT
let myTagFunction : (array<string>, array<'param>) => 'output

Refer to the docs to find a detailed example.

Import attributes

Import attributes is a JS feature that is currently in standardization, but is already implemented by many JS tools. Now, ReScript supports it too, as long as the compiler is configured to output ES6.

ReScriptJS Output
@module({from: "./myJson.json", with: {type_: "json", \"some-identifier": "yep"}})
external myJson: Js.Json.t = "default"
Console.log(myJson)

@module({from: "./myCss.css", with: {type_: "css", \"some-identifier": "yep"}})
external buttonCss: string = "button"
Console.log(buttonCss)

BigInt support

ReScript now natively supports JavaScript's bigint type.

ReScriptJS Output
open! Js.BigInt 

let a = 9007199254740991n + 9007199254740991n
let b = 2n ** 2n

See big integer docs for more.

Array spread syntax

The spread syntax, which was already supported for records and lists for a long time, now also supports arrays!

RESCRIPT
let animals = ["🐶", "🐱", "🐷"] let moreAnimals = [...animals, "🐔", "🐴", "🐮"]

Hyphens in JSX tag names

We lifted restrictions on JSX tag names. This means you no longer need to escape tag names that contain hyphens:

Previously:

RESCRIPT
let x = <\"custom-tag" />

Now:

RESCRIPT
let x = <custom-tag />

This is particularly useful when dealing with web components, where element names tend to use hyphens.

Omit trailing undefined in external function calls

ReScript 11's uncurried mode allows for much more ergonomic external function bindings, because trailing units were not needed anymore. But, this comes with a potential problem. All arguments, whether they're actually supplied or not, were printed as undefined in the resulting JS. This is handled better now, as trailing undefineds are automatically omitted.

ReScriptJS Output (ReScript 11.0)JS Output (ReScript 11.1)
@val
external stringify: (
  'a,
  ~replacer: (string, JSON.t) => JSON.t=?,
  ~space: int=?,
) => string = "JSON.stringify"

let obj = {"test": 1}

let result = stringify(obj)

let result2 = stringify(obj, ~space=2)

%todo and warn-error

Inspired by languages like Elm or Gleam, we introduced a new extension point: %todo.

It is used to tell the compiler that some code still needs to be implemented and it will crash when exectuted.

ReScriptJS Output
let implementMeLater = (): string => %todo("This should return a string eventually.")

let x = implementMeLater()

Console.log(x->String.includes("x"))

We also made the compiler's -warn-error flag accessible by the build system, so that %todos and other warnings can be turned into errors in production builds.

SH
rescript -warn-error +110

See "Compile with stricter errors in CI".

Other changes

Of course we also got a bunch of other changes and bug fixes in this release. Check out the compiler changelog if you are interested.

v12 is next

v11.1 marks the completion of the v11 versions feature wise. We will of course continue to support the v11 release series with bug fixes and other important updates. With this release however, our focus for new feature development will move to v12. You'll hear more about v12 and the plans for that version soon.

Acknowledgements

Once again we want to thank everyone from the community who volunteered their precious time to support this project with contributions of any kind, from documentation, to PRs, to discussions in the forum. But especially we want to thank the following people, who helped landing this release:

@cknitt, @cometkim, @cristianoc, @diogomqbm, @enzo-pellegrini, @fhammerschmidt, @glennsl, @JonoPrest, @mununki, @kevinbarabash, @shulhi, @tsnobip, @zth.

That's it

We hope you enjoy the newest improvements as much as we do.

If you find any problems with this new release, make sure to report them here:

Want to read more?
Back to Overview