Comparing Flow with TypeScript

Chances are that you have already heard of TypeScript: an open-source programming language designed by Microsoft to be an extension of regular JavaScript, perhaps best known as the language used by AngularJS from version 2 onward.

With the goal of strengthening the JavaScript language to make large-scale application development easier, TypeScript integrates many modern programming features such as module, class and interface into the language.

Among those additions, the most noticeable one has got to be optional static typing (it’s called TypeScript after all!). Static typing can offer many advantages by providing the compiler a better understanding of the code you are writing, and the benefits can range from better error detentions to improving the documentation process.

Static type programming in its full technicolor glory ( image source )

That’s good and all, but did you know that Facebook also have their own project for incorporating the advantages of static typing into JavaScript? They call this project “Flow”.


What is Flow?

It’s a pretty cool icon, I must admit ( image source )

So what exactly is Flow, you might ask? Well, unlike TypeScript, Flow is NOT a programming language in itself; but rather, a “Static Type Checker for JavaScript”. What this means is that Flow is a productivity tool that you can download and install into your local environment, which in return will analyse your code to generate insightful information.

Being a static type checker, one of Flow’s most essential feature is the ability to catch Type Errors within your code. Here’s an example of a basic type error in Java (viewing in the Eclipse IDE):

Uh-oh, you caught me

As seen in the example above, because we declared the variable h as a String variable, the Java compiler knows that h should not be passed as an argument into the calcAreaOfTriangle method, and thus displayed an error message in my code editor accordingly. This kind of checking is done at compile time, meaning the above code has not yet been executed.

JavaScript on the other hand, due to being a dynamically typed language, will not perform such checks by default. Often times, instead of throwing a type error, JavaScript will attempt to correct itself. In fact, if you were to write the same code above using regular JavaScript, the interpreter will be smart enough to convert the "10" string into a number automatically.

But what if a type error caused the behavior of the program to change from what the programmer intended? For example, there exists a method that saves the user’s blog using the Blog ID as an integer, but a programmer called the method when passing in the Blog ID as a string instead! Even in cases like these, JavaScript might remain silent, so catching these errors can be very difficult at times. Flow aims to deduce, as much as possible, any part of the code that might have potential to behave in an unexpected manner and advise the programmer on how to deal with the problem accordingly.

In addition, Flow also provides the backbone needed for many useful IDE features such as Error Highlighting, Autocomplete, and Automated Refactoring. With this, even regular text editors like Atom and Visual Studio Code can be configured to support these features for JavaScript.

You can see more details about other Flow features here.


Why is Flow simpler than TypeScript?

So we know that this type checking mechanic is pretty amazing, but why would you want to use Flow instead of TypeScript if TypeScript also has the same feature, plus more? The following is several reasons that you might favour Flow over TypeScript:

Out-of-the-box utility

To take advantage of the features that TypeScript offers, a developer would have to learn how to use special TypeScript syntax such as Type Annotation and modify their code. Not only that, but the developer must also ensure that the type information they are writing is correct/is what they intended. Flow, on the other hand, can automatically infer type information from existing code by using a technique they called “flow analysis” (it’s how they got the name!), and pick up any type errors by itself.

All you need to do to get this functionality (aside from installing and configuring Flow, of course) is add a single line of code:

/* @flow */

at the beginning of your JavaScript file, simple as that.

Though with the release of version 2.0, TypeScript is also starting to be able to infer type information automatically, but it has a long way to go before being able to provide insight as in-depth as Flow.

“In fact if you write a 10,000 line long file with no external dependencies with no types whatsoever. Flow should still be able to point you to where the errors are.”

James Kyle, a member of both the Babel and Flow teams

Even so, keep in mind that taking the time to write type annotations can enforce stricter checks that Flow would have missed otherwise. An example of this can be seen here.

Better compatibility with some libraries/frameworks/compilers

Who will come out on top? ( image source )

AngularJS, itself built in TypeScript, will naturally have native support for programming in TypeScript. React, a very popular JavaScript library also developed by Facebook, works very well with Flow. While it is true that it is possible to use TypeScript with React, the React ecosystem simply does not work well with TypeScript, often requiring additional adjustment to your code such as casting that otherwise would not be required at all. In this sense, if you would like to use some specific technologies such as React and Babel in your projects, you will most likely have an easier time with Flow.

The ability to retain JavaScript “purity”

One thing that Flow can do but TypeScript cannot is the ability to take advantage of the static type checking functionalities without the need to write “non-standard JavaScript code” (code that requires compilation back into regular JavaScript). This is achieved by writing type annotations within comments rather than in the executable code itself. An example by the Flow development team can be seen below:

This piece of code will execute in the same way as regular JavaScript. So by using this feature, even if your projects have trouble integrating the ‘Flow to regular JavaScript’ compilation process, you can still use Flow without any trouble. Another reason why you might want to use this feature could be that you want to keep the JavaScript as simple as possible (many developers will be working on the same project etc.).


Creating Sample App using ES6 & Flow

So are you ready to try using Flow in a JavaScript project? Due to the fact that we are using Flow instead of TypeScript, we won’t have access to the aforementioned “modern programming feature”… at least not right off the bat. Instead, we will combine Flow with the Babel compiler so that we can write our code in ES6: what some people call “next generation JavaScript”.

Let us begin by creating a simple “Hello world” program with two classes! There will be an example answer given in each step; but for good practice, you should try writing your own solutions!

“It’s alive, IT’S ALIVE!”
This tutorial assumes you understand basic HTML, JavaScript, and Object-Oriented concepts.
  1. First of all, use this website and follow the instructions to set up a new project with Babel. You can select any configuration you want.

2. Follow the instructions in this official guide to install Flow into your project. Be sure to select the following options:

  • Package Managers: npm
  • Compilers: Babel

3. Create a new html file (or alternatively, edit an existing html file such as main.html ). The<body> section of the file should have:

  • 2 locations where text can be displayed (e.g. label, h1)
  • A place to enter text (e.g. a Text Field)
  • A button.

Something like this:

4. Create a new js file, and we’ll call it helloWorldMessage.js. This js file will be our first class file, and its only responsibility is to provide a method where a message (in this case, “Hello, World!”) can be retrieved.

Something like this:

From now on, don’t forget to include the line:
/* @flow */
at the beginning of all of your js files!
Also, be sure to run the Flow checker on your code before moving onto the next step! There’s a good chance that Flow will pick up some “errors” even if your code works correctly. Fear them you should not, but rather, think of them as opportunities to make your code less prone to errors.

5. Create a new js file, and we’ll call it customMessage.js. This js file will be our second class file, and it’ll be a little bit more complex. This class will have:

  • A setter method for storing a name ( string ).
  • A setter method for storing a date&time ( Date ).
  • A getter method that will produce a message containing: The stored name, the current date&time, and the stored date&time.
  • A constructor that sets up a button click event that will: Take the text entered by the user ( string ) and the current time ( Date ), call the setter methods, and display the message returned by the getter method in one of the HTML locations “where text can be display”.

Something like this:

6. Create a new js file, and we’ll call it main.js. This js file will execute the following code when the webpage is ready:

  • Create an instance of the class that was declared within helloWorldMessage.js and customMessage.js .
  • Display the message returned by helloWorldMessage ‘s getter method in the other HTML location “where text can be display”.

Something like this:

And that’s it. Try running your website from your html file, does it work as expected?


Conclusion

In conclusion, when developing large scale web applications, having a static type checker can help safeguard your program, as well as helping you to eliminate existing errors. Compared to TypeScript, Flow can easily be integrated into existing projects and should fit in without causing disruptions to the JavaScript build process. If TypeScript just isn’t your cup of tea, but you would still like to improve the robustness of your code, then go on and give Flow a shot!