I started using Flow in early 2016, and after joining Home this year, I switched over to Typescript. I have to confess I’ve faced challenges with both, but I’m still sold on typings.
tldr; You’re not a machine. You just can’t catch all bugs and know your (and your team’s) code by heart and it’s not your job. So add static types!
“Yeah but you know I don’t have time to do that.”
Ok, let’s clarify something here. If you spend your days making 100-line apps or scripting stuff in a console, maybe adding types is not the thing for you.
But if you’re working on bigger apps or libraries, spending a couple of hours to set up and learn the basics of TS or Flow will bring you lots of advantages, including:
- Catching errors before runtime. This is so important. Libraries such as Tcomb are cool, but you still need to run your code to get the error. Plus if you have static type checking, you can have runtime type checking (see flow-runtime and ts-runtime for example)
- Self-documented code. You can find out how to use a component or function just by looking at it. We all know how hard it is to get into someone else’s code. Adding types to your code make this easier.
- The ability to code faster. Yes really. Having static types gives you the power of smart auto-completion, a better understanding of the code without having to do any reverse-engineering, and a way of avoiding time-consuming mistakes.
- A code base that scales. I read somewhere that talking about “scaling” make people think you’re smart, so I decided to add this line.
But honestly, it really helps. When you rename a function it will automatically update all occurrences in your app. Combined with React, you can change the props of a component and immediately know if you broke something. You end up with a more robust and reliable code base.
I see a lot of guides, sometimes really good ones, focussed on the structural and implementation differences between TS and Flow — TS is a language, Flow isn’t etc. — but these aren’t the issues I’m concerned about on a day to day basis. I just want to have auto-completion, a way to catch errors as I code, easy refactoring etc…
So instead of focussing on the structural stuff, I’m going to look at some of the performance differences between TS and Flow which I encounter in my daily routine:
I don’t like googling errors. Errors should be as easy as possible to understand. Let’s take the following example:
I clearly have an issue with my code. Let’s see what warnings TS and Flow are giving me:
Typescript clearly gives us the solution to fix the problem, whereas Flow just flags a type incompatibility.
For me this one is the biggest issues with Flow: Instead of having the error in the <Title /> component like in Typescript, the error shows up in the Title function.
While Typescript raises the correct error, Flow doesn’t complain at all when attempting to pass non-existent props 😕.
This is an areawhere Typescript impressed me, and where Flow is still behind.
Let’s imagine I have this amazing Todo List and I want to delete an item. Not rocket science, I’ll just create an action as follows:
And in my reducer:
Type inference in Flow is not as good as in Typescript. In fact, Flow won’t even complain if I misspell
DELETE_ITEM, whereas TS would. Better yet, I could avoid this problem altogether in TS by taking advantage of auto-completion.
Integrations with Atom and VS Code are fine, but from personal experience, Typescript remains faster than Flow, especially on large projects.
So it looks like Typescript is clearly the best choice, or is it?
If you have an existing project then integrating Flow will probably be easier, as it’s designed for that.
With React and React-Native, Flow works out of the box. Flow comes with a babel plugin, which makes it super easy to integrate, while with Typescript you’ll have to set up ts-loader or awesome-typescript-loader with some the appropriate Webpack configuration (although this process can be made easier with tools such as Haul ❤).
Upgrading to a new version of TS almost always leads to errors. We’ve been stuck on Typescript 2.3 for a while because upgrading to 2.4 was causing a big issue with a third party library (Immutable.js).
Flow, meanwhile, has taken steps to make the upgrading process less painful.
Flow 0.53 introduces flow-upgrade - a powerful tool which can save you hours when upgrading from one version to another!
This is a nice move Flow 👏 .
Both Flow and Typescript are evolving, and improving very fast. With the release of 0.53 Flow has significantly improved its support for React. 👍
Babel will support Typescript in v7 , which will make using Typescript easier.
Adding TS or Flow won’t make your code base invulnerable to Typing issues. You can still break the Types quite easily, especially when you start working with non-typed librairies, or if your setup is too permissive.
I know it may be annoying at the beginning, but make sure your settings for Flow or Typescript are super-strict. Trust me, it’s worth it in the long run. It will make your app way more reliable.
Here’s an example of some of the things your compiler should be picking up on:
// Example of tsconfig file
Static typing is not the golden ticket. Good coding practices are still required. You’ll still need your unit and e2e tests to be sure that your app is running as expected.
Both Flow and Typescript are awesome ❤ and I’m really happy that both of these solutions exist. A bit of healthy competition between the two libraries forces both teams to be better and make the best features.
Now that I’ve helped you choose a typing solution, it’s up to you to type your code and your libraries 🚀
“Wait! You can’t finish like that! What should I use then?”
Well, from my personal experience, Typescript feels smoother while coding, but when it comes to integrating third party libraries (e.g. Prettier, Haul, React Native) into your project, Flow throws fewer issues.
If you have an existing code base, maybe Flow is the way to go. But if you’re starting from scratch and want a solution that feels really reliable, give Typescript a try. Keep in mind that TS and Flow syntax are very similar, so you can always switch if you change your mind.
**Those examples are based on Typescript 2.4.1 and Flow 0.51.1