DEV Community

loading...

Writing Javascript from the future. A brief intro to Rescript.

Guilherme Luiz
software engineer and tech enthusiast
・3 min read

The ignition point

Rescript is a strongly and statically typed functional programming language.

Alright, so what?

Part of Rescript's magic comes from its interoperablity and similarity with the well known Javascript. This means you can use JS libraries in Rescript code and use Rescript code in projects with JS. The compiler transforms the Rescript code into readable JS or TS.

Showing the code

Here is an example of interop with external JS libs.

@module("@headlessui/react")
external Transition: () => React.element = "Transition"
Enter fullscreen mode Exit fullscreen mode

Pretty simple, I'd say.

Here are some code chunks showing off some syntax.

let student = {
  "name": "John Cena",
  "id": 123456
}
// this is both valid JS and Rescript
Enter fullscreen mode Exit fullscreen mode
let multiply = (a, b) => a * b
let result = multiply(10,4)
// this is also both valid JS and Rescript
Enter fullscreen mode Exit fullscreen mode

Why should you use it?

Until now, i've only said its similarities to Javascript, I have not given any examples on why is it usefull or even worth using. Here are some Rescript built-in features that I find extremelly usefull.

  1. Strong, static and inferred type system
    Rescript is a language that uses the ML family type system behind the scenes, that is why it is bullet proof. Here is a small comparison between Rescript and Typescript type inference.

    
        let sumIfTrue = (test, a, b) => {
          let term1 = if test(a) {a} else {0}
          let term2 = if test(b) {b} else {0}
    
          term1 + term2
        }
    
        let isEven = x => mod(x,2) === 0
    
        let result = sumIfTrue(isEven, "string", 2)
    
    

    The code above has an error, the rescript compiler knows that the parameter a must be a number. (Example in Rescript Playground)

    
        const sumIfTrue = (test, a, b) => {
          let term1 = test(a) ? a : 0;
          let term2 = test(b) ? b : 0;
    
          return term1 + term2;
        }
    
        const isEven = (x) => {
          return x % 2 === 0;
        }
    
        const result = sumIfTrue(isEven, "string", 2)
    
    

    The Typescript compiler will not automatically infer the types of any function, hence this is valid TS and might break in a real world app. (Example in Typescript Playground)

    The examples above are really simple and the mistakes are easily identifiable, but we must consider that in larger and more complex applications these mistakes gets harder and harder to identify manually.

  2. Fast compile time
    Many developers do not feel the need of this feature, because they have high-end machines and build times in big TS projects already gotten so high, that we migh have lost perception of speed in this case. Rescript's compiler makes type checking fast again.

  3. JSX
    React can be used out of the box with rescript, since JSX is part of Rescript's syntax. I will talk a little bit more about this in a future article. If you are super interested, checkout out the official docs.

  4. No null or undefined
    This wipes out a big amount of bugs, since there are not Cannot read property foo of undefined or undefined is not a function in rescript code. However, rescript has the concept of nullish and optional values safely implemented in the language core.

  5. Pattern Matching and Labelled arguments
    They are not something that you look for until you realize how usefull they are. After that, you will miss these features in any other language that does not have them.

let getIshColor = (~color,~suffix) => {
  let ish = switch color {
    | "blue" => "blueish"
    | "red" => "redish"
    | "yellow" => "yellowish"
    | _ => "unknownish"
  } 
  ish ++ " " ++ suffix
}
let color = getIshColor(~color="red",~suffix="car") // no more confusing argument orderantion!
Enter fullscreen mode Exit fullscreen mode

Why not to use it

Using something new and not tested at scale.

  • It is natural that human beings reject something that changes their day to day directlly. The principles of rescript might be a pain in the beginning, even tought they will pay off in a medium/long term. About the "tested at scale": rescript is used by Facebook's team and many other companies, such as Drafbit. The technical quality of their products cannot be contested, so the point here is about quantity. We only know something can be safelly used until many people start using it.

Outro

For this article, that is all. I am probably going to cover other important points of rescript in future posts, but for the introduction I feel like this is enought.

Thanks for the reading and see you in the next one.

Discussion (5)

Collapse
mgtitimoli profile image
Mauro Gabriel Titimoli • Edited

I love ReScript, but I believe it has 2 issues, one that could be classified as a preference, and the other that imo, it is a major one:

  1. Module unique names: this restriction comes from OCaml, but it means that you end up prepending modules with folder names (ignored by the compiled) to make them unique.
  2. No source maps: this is pushing me back to use ReScript on a project as for me, it is super important to be able to debug the code, and without source maps this is impossible unless you log to the console like the old days.
Collapse
guilhermells profile image
Guilherme Luiz Author • Edited

Hi @mgtitimoli , thanks for your comment!

The source maps feature has been requested many times to the rescript team, however they do not see it as something necessary, at least not for now. Personally, I have not missed it that much (yet), because you can insert breakpoints in the generated .bs.js files.

Here are some threads on github and on rescript's blog talking about this topic:

Collapse
mgtitimoli profile image
Mauro Gabriel Titimoli • Edited

Thanks to you @guilhermells for taking the time to write this article!

Yeah, I'm watching those issues as well, imo, having the ability to debug is something than sooner or later you end up needing, sure, you can log to console to reduce a bit the pain but the experience is not the same.

This is not something exclusively of ReScript, I feel the same with Elixir that is hard to debug vs for example with TypeScript that with the sourcemaps the experience is the same as with vanilla JS.

Collapse
lukeshiru profile image
LUKESHIRU

I tried ReScript in the past, but the editor integration was kinda subpar. Have you tried it with VSCode? And if so, how's the developer experience with it?

Collapse
pontakornth profile image
pontakornth

I tried it with VSCode. It's not really good but not that bad. I really like the concept. The problem is I cannot use libraries I intended to use such as Firebase, it's too much work to deal with. My skill is not sharp enough.

Collapse
guilhermells profile image
Guilherme Luiz Author • Edited

My experience was pretty nice, due to the rescript-vscode extension. The rescript team keeps releasing enhancements to this extension periodically, it is pretty sweet now compared to a few months ago!

github.com/rescript-lang/rescript-...

Rescripts bindings are kind of an overhead sometimes, especially when we talk about big and complex libraries, such as firebase. In this case, you could create binding for specific functions to use them in .res files and/or use ts or js to manipulate other firebase functions that you are not feeling like binding to rescript.