This Apress imprint is published by the registered company APress Media, LLC, part of Springer Nature.
The registered company address is: 1 New York Plaza, New York, NY 10004, U.S.A.
JavaScript is vital to the modern web ecosystem. It’s used in the front end to implement websites and other user interfaces, and used in the back end to implement servers for websites and APIs.
Part of JavaScript’s ubiquity is due to its ease of use. JavaScript is dynamic and flexible, making it easy for people to pick up. However, this strength becomes a weakness when working on large web applications with multiple developers – the only way to know that JavaScript code works correctly is to actually run it, and it’s relatively easy to make mistakes when programming in JavaScript.
What if there was a way to detect bugs in JavaScript before running the code, or prevent many classes of bugs altogether? What if there was a language that was concise and elegant that made it easy for programmers to write complex web applications and hard for programmers to make mistakes?
Enter ReScript.
ReScript is a language designed for writing web applications. It brings a lot to the table: static typechecking, a strong type system, and powerful language features that will change the way you program.
Static typechecking – Catch bugs in your code without having to run it: undefined values, missing cases, incorrect types, and more.
Sound type system – ReScript programs that pass typechecking cannot have runtime type errors.
Type inference – ReScript automatically infers types based on how variables are used, allowing you to enjoy the benefits of type safety without having to annotate every variable and function.
Immutability – Peace of mind while you program with variables and data structures that cannot be unexpectedly modified under your nose.
Algebraic data types and pattern matching – Cleanly define and elegantly manipulate complex data.
First-class bindings for React – Write React elements and JSX directly inside ReScript files.
ReScript is safer – Unlike ReScript’s battle-tested and sound type system, TypeScript’s type system is unsound, so it is still possible to have runtime type errors in a valid TypeScript program.
ReScript is faster – ReScript’s compiler is much faster than TypeScript’s compiler, allowing for a smoother development experience when working in large code bases.
ReScript is more concise – ReScript’s excellent type inference means that programmers do not have to write as many type annotations in ReScript programs compared to TypeScript programs.
Although ReScript is a relative newcomer to the web ecosystem, it’s actually based on technology that has been battle-tested for years before ReScript even existed. ReScript itself has proven successful as well. Most notably, Facebook used it to build the web interface for Messenger – a product used by hundreds of millions of people – with a code base containing thousands of files.
The lineage of ReScript can ultimately be traced back to the ML family of languages originating from the 1960s. In particular, ReScript is directly based on OCaml, a general-purpose programming language that was developed in the 1980s and used today for systems programming in academia and industry.
In 2015, Jordan Walke, the creator of the React web framework, developed a toolchain and alternative syntax for OCaml called Reason.
Reason was designed to bridge the gap between the web and OCaml ecosystems – it could be compiled into both native machine code and JavaScript, allowing web developers to take advantage of OCaml’s features. Static typechecking and OCaml’s sound type system eliminated many common bugs in JavaScript code, and OCaml’s immutability and functional style was a great fit for React.
Reason was compiled to JavaScript using a compiler called BuckleScript, which was developed at Bloomberg around the same time Reason was being created at Facebook.
Around 2020, the BuckleScript project created a new language based on Reason that could only be compiled to JavaScript using the BuckleScript compiler, and so ReScript was born.
ReScript has different syntax and features. While it looks and feels more like JavaScript, ReScript is still based on the battle-tested compiler and type system as Reason and OCaml, so it has the same type safety benefits as its predecessors.
ReScript can only be compiled to JavaScript. By dropping support for native compilation, ReScript has a simpler toolchain and standard library, along with a feature set better suited for web development. This makes ReScript easier for newcomers to learn and allows for smoother integration with other web technologies.
Like some other statically typed languages in the web ecosystem, ReScript code is transpiled to JavaScript. This means that ReScript code doesn’t directly run in the browser or on the server. Instead, the ReScript compiler checks that the code is valid and generates JavaScript files, which can then be imported and used like any handwritten JavaScript file.
Being able to run in any environment that supports JavaScript allows ReScript to be used for full-stack web development, from client-side code that runs in the browser to server-side code that runs in Node.js.
Since ReScript code is exactly the same as JavaScript code when it runs, ReScript programs can easily import and use JavaScript libraries, while JavaScript programs can call ReScript functions as easily as they can call other JavaScript functions.
Functional programming is a paradigm of programming that focuses on the application and composition of functions.
In functional languages, functions are first class and can be used like any other value (bound to variables, passed as arguments, or returned from other functions). Complex programs are written by composing multiple smaller functions that apply transformations to data. This can be contrasted with the imperative and object-oriented style of many popular languages, where programs look more like a series of commands that read and update memory. It’s important to know that most languages are not purely in one category or the other; many languages fall somewhere in the middle of this spectrum, and features from functional languages are slowly being adopted by other languages. For example, ReScript is more functional but it also has imperative features like loops, while JavaScript is more imperative but it also has first-class functions.
Programming in a functional style has many benefits – programs are cleaner and more concise, and logic is more declarative making it easier to trace the flow of data through a program. The ability to compose functions together and write functions that accept other functions as arguments (higher-order functions) makes functional languages very flexible, and the greater emphasis on immutability and purity makes it easier to understand, write, and test programs.
As a disclaimer, I’m not some functional programming purist here to convince you that functional programming is the best way to solve every problem. Instead, I view functional programming as a useful tool in a programmer’s tool belt, albeit a tool that not enough people know about or know how to use.
Unlike many other functional programming books, the explanations in this book are designed to be accessible to those without a formal background in computer science. I do not expect readers to have experience with statically typed languages or functional programming concepts.
This book is written for anyone who is interested in learning ReScript or wants to learn the basics of functional programming using ReScript.
The book is structured as an overview of ReScript’s features, building up from the basics to eventually cover complex data types, pattern matching, modules, and finally writing a minimal web application using ReScript.
Along the way, you will learn functional programming concepts like higher-order functions, immutability, and purity, which will help you think about and write software differently, even when you are not using ReScript.
Chapter1 – Language basics: expressions, binding, and control flow
Chapter2 – Functions: higher-order programming, recursion, and purity
Chapter3 – Composite data types, pattern matching, and error handling
Chapter4 – Records and objects
Chapter5 – Lists and arrays: map, filter, and reduce
Chapter6 – Collections: sets, maps, stacks, and queues
Chapter7 – Modular programming: modules and functors
Chapter8 – JavaScript integrations: bindings, dealing with JSON, and more
ReScript projects are set up just like modern JavaScript projects, except we have an extra development dependency on the rescript package.
Before we begin, make sure you have Node.js v10 or higher, and npm. To check the version of Node.js you have, run node -v in your terminal. If you don’t have Node.js installed, you can find installation instructions at https://nodejs.org.
Once you’ve confirmed that you have the right version of Node.js installed, create a new directory for your project, and run npm install rescript@10 to install v10 of ReScript.
The scripts we added in package.json are used to run the ReScript compiler to compile our ReScript to JavaScript.
npm run build will compile all the ReScript files in the project.
npm run start will start a process that watches the project and automatically recompiles whenever anything changes.
The dir field specifies which directory ReScript source files are located, in this case under the folder src. For every ReScript file Foo.res under src, the compiler will output a JavaScript file named Foo.bs.js in the same location as the original source.
Now we’re ready to write some ReScript!
ReScript is a compiled language – this means that the ReScript files that we write are not being run directly by the browser or Node.js. The compiler checks to make sure our ReScript code is valid – syntax is correct, function calls and values are the right types, etc. – and then it compiles the ReScript files into JavaScript. The browser or Node.js will run the JavaScript the same way they would for JavaScript we wrote by hand.
You can run the JavaScript file using node src/HelloWorld.bs.js to print “hello, world” to the terminal.
Since ReScript compiles to JavaScript, it can be used for both client and server applications in a variety of environments – your browser, Node.js, etc. For the purposes of this book, we will be executing ReScript programs in Node.js.
As you read through the examples in the book, I encourage you to copy the examples into your code editor or the ReScript playground at https://rescript-lang.org/try so that you can compile and run the programs yourself. As you experiment with ReScript for yourself, make sure to inspect the compiled JavaScript output of your ReScript programs to get a deeper understanding of how ReScript works under the hood. You’ll find that the generated JavaScript code is quite readable!
is a professional software engineer at Meta working on infrastructure for WhatsApp. He has previously worked on Facebook Messenger, including the web interface which was written in ReScript. His technical interests include functional programming, compilers, and data visualization, which he writes about on his blog at www.yangdanny97.github.io.
is a software architect/engineer working with C/C++, Java, and different application containers, in particular with WebLogic Server. He has developed various applications using JEE, Spring, and Python. His areas of expertise also include OOP, Java/JEE, Python, design patterns, algorithms, Spring Core/MVC/security, and microservices. German has worked with performance messaging, RESTful API, and transactional systems. For more information about him, visits www.linkedin.com/in/german-gonzalez-morris.