Introduction to Flow: Flow vs Typescript

December 2017 · 8 minute read

Intro: Flow vs TypeScript

This is going to be part 0 of a 20-part series of posts discussing Flow. I have trouble claiming any credit for what I will write in it as I am not doing much more than translating, transcribing and (occasionally) annotating what Illya Klymov said in his video series on Flow (Russian) without even changing the format. I am doing this for anybody who can benefit including myself as I have an easier time learning from written posts rather than seeking on videos. With that said, let’s get into it.


Within the Russian web and even on the English web, there is little educational content about this excellent and absolutely under-rated static typing system. Within the realm of my abilities, I will attempt to change that.

First and foremost, I would like to say that after some period of stagnation, work on Flow has once again actively resumed. As such, at the end of each post I will mention which version of Flow it concerns. This isn’t necessary for foundational concepts as the odds of them ever changing are slim but it is important for nuanced edge-cases as they are constantly improving. For example in version 0.53 (If I remember correctly), Flow’s relationship with React was completely re-written and I will not hesitate to say that it put Flow on a whole new level. In master I see changes that fundamentally improve error-detection and type inference.

But before getting into all that, let’s start off by discussing the problem of choice: Of course, we all want to believe that the technology we chose is the best and the most awesome; however looking at the reality, we see that today, on the last day of 2017, Flow has the role of the under-dog which is quickly catching up to Typescript (Catching up as defined by metrics of community size and support).

Why would I want to choose Flow and why would I need to choose at all?

Firstly, if you are working with Angular, I absolutely recommend against choosing Flow as Angular itself is built around Typescript and as a consequence, Angular has fantastic first-class Typescript support. I have not seen a single Angular project written in plain JavaScript and naturally not in Flow.

Secondly, if you are someone who prefers the convenience of the tooling over the power and possibilities of them, then Flow is once again off the table. This is because Flow is currently being developed by a very small, and sadly by a very unresponsive community. Facebook doesn’t seem to want to build a very large community around Flow for some reason (They could however, if they wanted to as they did so with React). Because of this, we are in a situation where there is only a single “Officially” supported way of using Flow which is with Nuclide in which using Flow is superior to all the other editors combined. If we take WebStorm for example, we can feel that Flow is truly a second-class citizen. Meanwhile Typescript has a dedicated team working on it and WebStorm can push Typescript’s typing power beyond its server and provide even more type inference than what would usually be available. This topic has an excellent talk which was presented at HolyJS Moscow 2017 (The recording wasn’t yet published online). In summary, if you will be working with Flow, your workflow will probably be supported by the broader community instead of the core developers.

Another issue with Flow is that the number of available pre-written typings is far, far lower than what Typescript has and it is necessary to admit that sometimes it will feel that you are alone the entire room and if you have a problem you will rarely receive help especially if it concerns fundamental quirks.

You may want to ask me at this point, why would I want to use Flow if it has all these issues? Especially if it has two direct competitors (Typescript and Reason)? Why would I want Flow?

To that question you can easily find the answer just by looking at the documentation of Flow and Typescript. When you take a typing system you have two options on which you would want to focus: Soundness and Completeness.

Soundness: the ability of the typing system to detect issues that might occur in run-time. It looks at your code and your declared types and the type inference system figures out any inconsistency that might occur in a theoretical scenario.
Completeness: the ability to determine issues that will occur during run-time.

Plainly said, you can see soundness as a pessimist that will look at the worst case scenario and will pull out all sorts of unlikely issues and demand that they be fixed. Meanwhile, completeness is an optimist which will tell itself that there may be an issue but based on how you are using it, it will not arise and thus will not pester you about it.

In an ideal world, we would see a system where a system fully incorporates both Soundness as well as Completeness which will then co-exist and capture all actual issues. Sadly, we do not live in an ideal world. Especially with a language such as JavaScript, a language which was primary developed without any types forces a fundamental separation: Flow makes an emphasis on Soundness such that you are forced to fix issues which would seem impossible to ever occur while Typescript prefers a more lax approach, trusts what you are doing and tries to make you comfortable. In other words, Flow is a system to make sure your code does not contain issues and Typescript is closer to a syntactic sugar (A bit unfair as Typescript is a super-set of JavaScript but it stands as a good approximation for sake of this comparison).

As such, when working with Typescript, you would work in it the same way you would typically work in Javascript: Write a bit of code, run it, test it, rinse and repeat. Meanwhile Flow allows you to write a lot of code and without ever running it be sure that it is clear of run-time errors.

Returning the issues stated earlier, if you are working on a UI-driven application which glues a couple dozen modules together, it may not be worth it to use Flow. Not only would you need to go through and fix all the issues it detects but you would need to manually write types for a number of modules as it almost guaranteed that not all of the modules you are using will already have pre-written types.

At last, let’s consider an example where Flow is absolutely needed: Consider a massive project which you cannot hold entirely in your head, consider a project in which you don’t know how every component works, consider a project which makes you weary that once you come back in half a year, you will not longer remember how it worked. Simply, consider a project which either really large or complex; this is when Flow will make your life much easier. Let’s be frank that on any large project where you have many components working together, external services tend to take a back-seat such as the API or the database that you happen to be using to instead focus on the core business logic which you actually write yourself and can thus apply strong and comprehensive types to. This is the killer feature of Flow, it can infer the types for all your external services such that you end up writing perhaps 3 or 4 times fewer type declarations than in Typescript or anything else.

Conclusion

In conclusion, I hope that this post properly explained the pros and cons of Flow and transmitted the idea that if you want to be absolutely sure in the infallibility of your code, Flow is a good choice.

If you are (God forbid) developing on Windows, you are going to feel that Flow’s Windows support is always late when comparing to Linux and MacOS. This is because Flow is primarily built by Facebook for Facebook and Facebook doesn’t care much for Windows developers. You may also encounter a few unpleasant issues here and there (few of which are unfixable).

If you try to use Flow with React, you will find that it works together beautifully, and predictably so as both are authored by Facebook.

Lastly, regardless if you will use Flow in the long-term, it is worth giving a try as it will fundamentally improve how you write code through the understanding of how types work in the exact same way as using unit tests improves how you write code through making your systems easy to test.


Following the development of Flow

The best way to follow where Flow is going is perhaps by looking at Flow’s commit. Flow is written in a fascinating language called OCaml which sadly increases the barrier to entry necessary to contribute to it.

This post was written for Flow 0.62