- I love JS, Why should I bother about Type Safety?
- Action Time: Show, Don't Tell – A Concrete Example Unveiled!
- Safeguarding Success: Unveiling the Power of Type-Safe Languages
- Breaking the TypeScript Mold: The Reasons Behind Our Unconventional Path
- Fast Compilation: Accelerating The Development Experience
- ReScript: Subset of JS, TypeScript: The Flip Side!
- Type safety is seamlessly integrated into the development process and guaranteed 100%.
- ReScript gives the feel of Functional Programming
- Ok, What else rescript has to offer?
- There are no Null and Undefined in Rescript!
- Dive into Examples for a Deeper Grasp!
- Dead Code Elimination: The Dead Code Slayer You Want!
- Rescript : The Seasoned JS Code Optimizer!
- Time for Verdict: Rescript Clear Winner?
We found ourselves having to decide between TypeScript and ReScript very pretty early in our journey. In this blog post, we'll delve into why ReScript emerged as a better fit for Hyperswitch, an open-source payments orchestrator that enables seamless integration with multiple payment processors via a single API.
I love JS, Why should I bother about Type Safety?
We as developers frequently encounter the challenging task of establishing and overseeing types throughout the application, aiming for a seamless process of error detection and adaptation to changes.
Without a robust type safety system, making basic alterations to your database's structure, your API layer's object definitions, or even how your web client perceives that object could lead to the absence or deformation of data somewhere along the sequence of instructions if each point of contact isn't updated correctly.
Action Time: Show, Don't Tell – A Concrete Example Unveiled!
For example, let's say you have a web app where you have to process user's contact information. Without a robust type safety system, if you decide to change the format of how phone numbers are stored in the database (like switching from a string to a numerical format), and you forget to update the API layer and the web client accordingly, you might encounter issues.
The web client may still use phone numbers as strings, expecting them to be stored as strings in the database, but the database is now configured to send numerical values. This mismatch in expectations could lead to breaking of application, as you may be expecting it to be a string and processing it likewise.
A robust type safety system would help catch these inconsistencies early on, ensuring that changes to data formats are uniformly applied across all parts of the system, maintaining data integrity and preventing such issues.
Simultaneously, the absence of types increases the chances of runtime code breakage with each modification. In larger codebases, this scalability of errors significantly hampers maintenance efforts and time-to-market efficiency.
Imagine you're working on a shopping website. There's a function that calculates the total price of items in a shopping cart. Now, you want to update it to include a new type of discount, like a percentage off.
Without type safety, if the function previously expected only integers and you now accidentally pass a discount value as a string or a different data type, this change could break the code during runtime. The absence of type checking makes it challenging to catch such errors before execution.
Now, imagine this in a larger codebase with numerous interconnected functions and components. Without a type system to catch potential issues early on, the risk of breaking code in various parts of the application significantly increases.
Safeguarding Success: Unveiling the Power of Type-Safe Languages
Numerous approaches exist for implementing a type system in frontend development. Some notable options include TypeScript, ClojureScript, PureScript, Scala.JS, Elm, JS_of_ocaml, ReScript, and the possibility of writing frontend code in languages such as C or Rust, facilitated by WebAssembly and JS bindings like wasm-bindgen.
Breaking the TypeScript Mold: The Reasons Behind Our Unconventional Path
We at Hyperswitch considered using TypeScript as it is widely adopted in industry. However there were certain concerns which tilted our decision in favour of Rescript.
What is ReScript?
In simpler terms, think of ReScript as a syntactic sugar on top of OCaml just like JSX is for JS.
So, even though you enjoy a more straightforward syntax, you're essentially working with the power of OCaml under the hood.
Fast Compilation: Accelerating The Development Experience
In the case of large codebases such as ours, the compilation time for TypeScript tends to be excessively prolonged especially for a monorepo with thousands of lines of code, resulting in a poor developer experience. Recognizing this challenge, we were aware that our project's expansion would inevitably escalate compilation times. In contrast, ReScript boasts remarkably swift compilation, mitigating the issues associated with prolonged compilation times. Thanks to Rescript, It stands out as one of the fastest compiler & build system for JS development.
ReScript: Subset of JS, TypeScript: The Flip Side!
ReScript's type safety is seamlessly integrated into the development process and guaranteed 100%.
The migration process to TypeScript takes a "breadth-first" approach, where you enable it for all files and add annotations throughout. However, determining the extent of gained type safety and measuring it can be challenging.
In contrast, migrating to ReScript follows a "depth-first" approach. Each piece of converted ReScript code is entirely clean. You convert one file at a time, and each conversion consistently enhances your safety.
ReScript feels like Functional Programming
What is functional Programming?
it's a style of writing code where functions are treated as first-class citizens, meaning they can be passed around and used as arguments just like other types of data. The focus is on using pure functions, which means they produce the same output for the same input and have no side effects.
We at Hyperswitch embrace functional programming to the core.TypeScript isn't exactly a functional language; it's more like bringing Java-style typing to the browser. While you can try to add functional features, it often leads to complicated and over engineered code. Instead of simplifying things, TypeScript can make them more challenging, whereas functional programming aims to make things simpler. On the contrary, ReScript offers much simple and robust functional programming approach.
Ok, What else ReScript has to offer?
There are no Null and Undefined in Rescript!
In ReScript, every value must have the correct type. When there might be no value or an expression could result in an error, ReScript uses variant types. These are like options (think of Haskell's Maybe) and results. They carry a value or information about its absence or an error.
Additionally, the ReScript compiler ensures that we account for negative scenarios through pattern matching, making our code more robust.
Dive into Examples for a Deeper Grasp!
Let's understand with the help of an example. We use something called the option type to show whether there's a value or nothing at all. In simpler terms, it's like putting the value inside a box labeled "Some" if it's there, or leaving the box empty, labeled "None," if there's nothing. So, an option type is a way of saying, "Here's something, or there's nothing at all."
Let's consider a function written in Rescript as below. This function accepts a parameter personHasACar and based on that value is assigned to a variable licenseNumber
Later on, when we unwrap and use such an optional value, it'd be forced to handle both cases i.e when a value exists and when it doesn't through pattern matching. If you don't handle all the cases a warning will be raised like below.
Below is the compiled JS code by Rescript for the example discussed earlier. Note the unwrappedValue is always neither null nor undefined.
Dead Code Elimination: The Dead Code Slayer You Want!
Rescript : The Seasoned JS Code Optimizer!
We as developers are often lazy writing highly optimized JS code. At the same time it is not so easy to achieve high level of low level optimizations. But, Rescript got us covered. ReScript's type system and compiler act as a natural guide, steering you towards code that is inherently performant by default. This includes effectively leveraging various Just-In-Time optimizations such as hidden classes, inline caching.
Again Let's take an example
Consider the below function written in Rescript to calculate factorial of a number, it accepts two arguments n i.e. the number whose factorial is to be calculated and other ans i.e. the result of factorial computation.
Now let's see what Rescript compiler makes out of this code.Below is the output JS code generated by Rescript.
ReScript supports tail call optimization (TCO), which means that certain recursive functions are optimized to avoid stack overflow errors. The compiler transforms the recursive call into a loop, optimizing the memory usage. Rescript is capable of making many more optimizations like this under the hood.
Rescript Clear Winner?
Not really, We used Rescript because we love functional programming. Moreover we choose Rescript over TypeScript as it is possible to leverage the power of vast, React ecosystem and widely used tools such as Webpack and have better type guarantees and more functional code than TypeScript.
The icing on the cake is that it prevents any unintentional efforts to mess up type safety, providing support even for those who are newer to the team.
But, if Object-Oriented programming is your thing, then TypeScript is the recommended choice.