Our Experience Migrating from Flow to TypeScript
Considerations for making the leap a soft and smooth landing.
If you are developing in JavaScript — or a language that has JS at its core, such as React Native — and you want to do type checking, you face a problem. JS is a dynamically typed language, meaning that type checking is performed at run-time. To save time, increase accuracy and reduce errors, you will need to rely on an additional tool to provide static type checking at compile time. Two of the most prominent tools to accomplish this in the JS ecosystem are Flow and TypeScript. In this post, we will examine the benefits and drawbacks of each and share why we ultimately picked TypeScript for our latest project at Equinox.
For past projects at Equinox, we opted to go with Flow. Flow is made by Facebook, the company behind and largest maintainers of React and React Native. Since this comes from the same folks who created React Native, as you might expect React Native and Flow have tight integration. In fact, there is no additional configuration needed to begin static type checking in your existing React Native Project with flow. Flow is also completely modular: want to adopt it for some files, and ignore it for any section where the code would be too difficult? No problem, simply include
// @flow
as the first line of your file, and flow will begin watching that file for type errors. This modularity is great for an in progress project, or one that wishes to only add static checking to certain sections.
As Equinox developed with Flow, however, we found there were some negatives as well. For one thing, the type checking wasn’t as sound as you would expect. As our project grew in size, we began to encounter various situations where Flow had failed to catch a potential type conflict, or where a developer implemented a type that was not as strict as expected. Since soundness of type checking is the entire purpose of Flow, that’s not ideal. In fact, even within Facebook there are teams who have decided to move away from Flow into a different solution. For example, yarn moved from Flow to TypeScript. So has jest. When it came time to spin up our latest project at Equinox Media, Equinox+, we of course wanted to start with a fresh tech stack that represented the best options available today.
Looking at recent developments in technology, and always on the lookout to leverage our new stack into a more cutting-edge solution, we made the following choices:
- Adopt GraphQL over Redux
- Change our analytics provider
- Adopt a hooks-first approach
- Switch from Flow to TypeScript
This post explores why we felt TypeScript was a better solution for us. I hope this information proves useful for you if you are trying to determine what type checking solution to implement in a new or existing project.
Syntax Comparisons
TypeScript forced us to be stricter with our code, as one would expect with a language that has strict type checking, but it was a very easy learning curve in syntax changes from Flow, while providing additional functionality compared to Flow. See some comparisons in the syntax for primitive as well as more advanced type declarations.
As mentioned previously, one advantage Flow has is that it works out of the box inside React Native projects, and can be adopted incrementally file by file. For those with existing projects who are ready to make the switch to TypeScript there are multiple migration tools from reputable maintainers such as Airbnb’s recently released tool for moving from Flow to TS. Khan Academy also provides a Flow-to-TS tool that has been around for some time, including an online IDE converter where you can see how the tool performs. Check it out here.
While Flow really shines in the setup, most modern projects will implement some sort of configuration regardless to select which linting, styling and other coding rules the IDE and Typechecker will help you adhere to. Bearing this in mind, I would say integrating TypeScript into a project is not that much work, particularly with all of the babel plugins for supporting it, and boiler-plate cli generators. For example, running:
npx react-native init MyApp — template react-native-template-typescript
With the template flag set to TypeScript will take care of the majority of setup for you just as easily as a project relying on Flow.
Community Support
If you clicked on the links above, you would have noticed commentary indicating that TypeScript is a growing industry choice. Why? In a word: acceptance. The JS ecosystem is increasingly revolving around TS with great Microsoft developer support, as you might expect from Microsoft and their history of developer tools.
One of the things Microsoft did was include tight integration of TypeScript into their popular IDE, VSCode. This is brilliant since we now get full type checking, auto complete, and compiler errors right in the editor out of the box without installing any additional extensions.
For example, note how VSCode provides TypeScript support with in-line error checking with no additional configuration!
This is another point for TypeScript, as Facebook has no IDE or comparable out of the box integrations for VSCode. Developing in this environment is much easier and productive. Having Microsoft as a backer of such tools gives us confidence that these tools will be around — and continuously maintained — in the future.
A final point that reflects strongly on TypeScript is the vastly growing number of open source libraries that have implemented TypeScript as well, choosing it over alternatives like
Flow or the PropTypes library.
Conclusion
After considering the advantages and drawbacks of both TypeScript vs Flow, it was clear that TypeScript had a larger community, richer IDE integrations, more forward momentum, and stricter checking. The fact that Microsoft has been increasingly involved with React Native both in their own apps as well as their development ecosystem also helped sway things in their favor. Really, this was an easy choice for us, and one that has given us tons of bonuses and no regrets. While we had the benefit of creating a new app from scratch with TypeScript, and Flow is more of a modular approach that could be appealing to existing projects, the long-term benefits of TypeScript, and ease of setup with the boilerplate generator or migration using Airbnb’s tool, mitigate any of the potential drawbacks.