Flow vs TypeScript: Which Is Better Suited For Your Next Project?

ProfilePicture of John Kapantzakis
John Kapantzakis
Senior Developer
Two developers in front of giant Flow and Typescript logos

As projects become more complex for JavaScript developers, new tools and practices arise to improve code quality and workflows. In addition to unit testing, static type checkers such as TypeScript and Flow are becoming the norm among professional development teams.

Regardless of project size, the benefits of making code more comprehensible while also catching errors during the development phase have proved invaluable. As a result, the question being asked by many is: which tool should I use, Flow or TypeScript? For the context of this article, we’ll be focusing on and using examples with respect to React (given its current popularity), but the analysis will be relevant regardless of what framework you may be using.

As a professional web developer with over five years of experience, I’ve worked on large JavaScript codebases without the use of a type-checking tool. I’ve experienced the associated pitfalls and have seen situations where runtime errors that could have been caught in dev reached production more times than I can count. For the last three years, I’ve primarily used TypeScript, and I can tell you that as a result these kinds of errors were effectively eliminated. Through side projects, I’ve also gained exposure to Flow and have found it to be a great tool to add type safety to a new or existing JavaScript codebase. It’s become clear to me that the use of some form of static type checking is essential in the modern JavaScript ecosystem.

In this article, I’ll provide a brief introduction to these tools and illustrate the way they function. I’ll also explain how to integrate both TypeScript and Flow into a simple React application to show them in action. Then, I’ll weigh their benefits and compare them in terms of functionality, ease of use, community support, and more. Finally, I’ll review the key points to help you decide which of these two tools is best suited for your project.

Table Of Contents

What Is TypeScript?

TypeScript is a programming language developed by Microsoft. It is open-source and is supported by a large and active community.

As mentioned on its official website:

“TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.”

Let’s focus on two words of the previous statement, “typed” and “superset.” The word “typed” indicates that TypeScript requires that the programmer declare the datatype of a given variable. The word “superset” indicates that TypeScript allows the programmer to use all the features that JavaScript provides, plus some additional TypeScript-specific features like interfaces, generics, decorators, etc.

The following images present a high-level overview of the way that TypeScript functions. The compiler receives TypeScript files (.ts or .tsx) and then “transpiles” them into valid JavaScript code that can be run by the browser.

Diagram of Typescript compiler from .ts file to .js file

Let’s take a look at some simple code written in TypeScript:

1function getName(person: IPerson): void {
2 console.log(person.name);
3}
4
5interface IPerson {
6 name: string
7 age: number
8}
9
10getName({
11 name: "John",
12 age: 38
13}); // logs "John"
14
15getName({
16 age: 38
17}); // Intellisense indicates an error: Argument of type '{ age: number; }' is not assignable to parameter of type 'IPerson'.
18

This is TypeScript in a nutshell. You can find a more detailed analysis and guide on how it works in one of our recent articles, What is TypeScript?  As we can see in the above block, we declare a function that expects an object that has two properties, name and age of type string and number respectively. When calling the function, TypeScript checks that the provided object is of the correct type, and if it isn’t – like in the second getName() call – the code will fail to compile and throw an error.

What Is Flow?

Flow, in contrast to TypeScript, is not a language; it’s described as a “static type checker for JavaScript”, and was developed by Facebook (the creators of React). We can use Flow by adding special annotations to our regular JavaScript files, indicating the types we expect, or we can just let the tool infer the expected types and warn us if it finds any errors.

Let’s take a look at the following code sample taken from Flow’s official documentation:

1// @flow
2function square(n: number): number {
3 return n * n;
4}
5
6square("2"); // Error!
7

Notice the first line of the above code? In order for the tool to know which files it has to check, we place a special “// @flow” comment in each file we want to be included in Flow’s monitoring process.

Just to clarify, in order to use Flow, you don’t have to change the extension of your files, instead, you continue to write vanilla JavaScript in annotated .js and .jsx files. If we had left the above code as is, the JavaScript engine would have thrown an error because of the annotations; therefore, as an additional step, we have to remove the annotations before we send this code to be executed. We can achieve this with Babel or with a lighter-weight alternative CLI tool called flow-remove-types.

Diagram of Flow-remove-types Babel from .js file + annotations to .js file

The above image shows how Flow annotations get removed in order for the final JavaScript code to be executable.

Flow vs TypeScript Integration with React

Now that we have seen an overview of TypeScript and Flow, let’s look at how these tools integrate with React. In doing so, we’ll later be able to compare both tools to identify their strengths and weaknesses and consider under what circumstances we would choose one over the other.

A Standard React App

The easiest way to create a React app is to use the create-react-app tool. We are going to create two identical React apps, one for testing TypeScript and one for testing Flow js. First, let’s look at the vanilla implementation of this tool by creating a React app without any type checking:

1npx create-react-app example-app
2

That’s it, our app is ready! Now we have to navigate to the example-app folder and start the development server to view our React app in action:

1cd example-app
2npm start
3

Your default browser should open a tab pointing at localhost:3000, and the following page should be rendered.

Browser screenshot of a React app instalation

Enabling TypeScript

If we’re starting from scratch, we can create a TypeScript-enabled React application just by using the –template flag like this:

1npx create-react-app react-ts --template typescript
2

And we would have come up with a fully configured React app with TypeScript enabled. That’s a great option for a new project, but let’s imagine we want to implement TypeScript in an existing React application.

First, we have to add the TypeScript package alongside some other dependencies. We are going to use yarn to install the packages but feel free to use npm if you prefer:

1yarn add typescript @types/node @types/react @types/react-dom @types/jest
2

After the installation completes, we are going to rename our existing .js and .jsx files to .ts and .tsx respectively.

If we then restart our development server, a tsconfig.json file will be created in the root folder of our project. This file is the TypeScript configuration file and, if needed, it can be customized to suit the needs of your project. Now you can start developing in TypeScript!

React Developing with TypeScript

Let’s create a React component that would get a list of items, as props, and render them as an unordered list.

1import React from "react";
2
3interface Props {
4 items: Item[]
5}
6
7export interface Item {
8 id: number,
9 name: string
10}
11
12function ItemsList(props: Props) {
13 const listItems = props.items.map(item => item.name);
14
15 return (listItems);
16}
17
18export default ItemsList;
19

TypeScript lets us declare the type of object that we expect by using interfaces. Here, we declare the Props interface that has a property item, an array of objects of type Item – another interface that has two properties, an id of type number and a name of type string, both required. Then, we say that the props parameter of our function component ItemsList is an object of type Props by adding the annotation props: Props.

Let’s implement the ItemsList component in our App.tsx file and declare a const called items, just as an array with a dummy object in it to see how TypeScript reacts:

Screenshot of React instalation using Typescript

You can see that an error is shown stating that Item must include the id and name properties. TypeScript is saving us from producing errors if we tried to run the application at this point. Now let’s remove the typing of our items const to see if this error goes away:

Screenshot of React instalation using Typescript -2

Even if we don’t declare that the items const should be of type Item[], TypeScript is smart enough to catch that using it with our ItemsList component isn’t safe. Now let’s fix this by adding two proper records to the component:

1const items: Item[] = [
2 {
3 id: 1,
4 name: "One"
5 },
6 {
7 id: 2,
8 name: "Two"
9 }
10];
11

We now see the application compiles and executes successfully:

Screenshot of React instalation using Typescript Complete

Thanks to TypeScript, we’ve saved ourselves from running potentially buggy code, while also making the code itself more readable by explicitly declaring the types used throughout our application.

Enabling Flow

Now let’s repeat the process with Flow. Starting from another newly created React app, we are going to install the flow package. Instead of using a template flag, we do the following:

1yarn add flow-bin
2

That’s all we need to install, much easier compared to TypeScript. We then need to add a “flow”: “flow” script to our package.json scripts section in order to run the following:

1npm run flow init
2

React Development with Flow

We are going to create the same ItemsList component as we did in the TypeScript example, in order to get familiar with Flow:

1import React from 'react';
2
3function ItemsList(props) {
4 const listItems = props.items.map(item => item.name);
5
6 return (listItems);
7}
8
9export default ItemsList;
10

In order for us to be able to start using Flow, we need to run:

1yarn flow
2

..and then Flow performs a check of all the files where we entered the “// @flow” comment. In our case, the check returns an error:

Screenshot of React instalation error using Flow

Let’s fix the above error by adding some types:

1// @flow
2import React from 'react';
3
4type Item = {
5 id: number,
6 name: string
7}
8
9type Props = {
10 items: Item[]
11}
12
13function ItemsList(props: Props) {
14 const listItems = props.items.map(item => item.name);
15
16 return (listItems);
17}
18
19export default ItemsList;
20

Now, if we run the check again, it reports no errors. As you can see, we have to run the same command every time we want to check our files with Flow. This is counterproductive, so we have to find a way to automate this process. For those using VS Code, the Flow Language Support can be used to automatically perform a Flow check after each save. Other IDEs will have equivalent capabilities, just search to find the implementation relevant to your environment.

TypeScript vs Flow Pros and Cons

Now that we have seen both tools in action, let’s contrast them against each other:

A table comparing the the key features of typescript compared to flow

TypeScript Pros

More than just a type checker: TypeScript adds additional data structures like Enums to JavaScript which developers coming from other languages may be missing. It also has interfaces, decorators, and other capabilities that make it more robust – enabling developers to write extremely comprehensive code. These features can be especially powerful in large and enterprise-style projects.

Developed by Microsoft: TypeScript is receiving regular updates and will continue to evolve. Many professionals predict that TypeScript is going to “take over the JavaScript world”, as Richard Feldman stated at ReactiveConf 2019. Given its growing popularity, it seems safe to say that TypeScript will have longevity greater than most other “trends” in the rapidly evolving JavaScript ecosystem.

Large community: As we will review below, TypeScript has a large and active community of people willing to contribute to its development and to help others by answering their questions or writing helpful tutorials. Beyond its official documentation, you can find plenty of unofficial resources on the subject of TypeScript.

TypeScript Cons

Steep learning curve: TypeScript can be strict and unforgiving out of the gate, turning developers off of it. It’s more difficult and complex to learn than Flow due to the fact that it’s more robust and is considered to be a programming language (or at least “superset” of JavaScript) on its own. TypeScript can also feel like an all-or-nothing approach, which can complicate things and slow down development in large projects with lots of dependencies.

Boilerplate code: Some argue that TypeScript precipitates a large amount of boilerplate code which can increase development time and make files harder to understand. Code minimalists may prefer the lightweight Flow (or no type checking at all) in this case.

Flow Pros

Ease of use: Flow is more forgiving than TypeScript, and serves as a softer introduction to static typing in JavaScript. It’s quicker to get up and running, and it also may be easier to add Flow into an existing project due to its per-file opt-in methodology.

Developed by Facebook: The company that developed React, so you can be sure that both tools are fully compatible and meant to be used together.

Flow Cons

Smaller community: Flow has a much smaller and less active community, as can be seen in the below section. This means there are fewer resources available for those trying to learn how to use it and debug issues that may arise. It may also mean that its future with respect to support and added features is more uncertain than that of TypeScript.

Less robust: Flow does type checking well, but that’s it. It lacks some of the “quality of life” features for developers that TypeScript has. An argument can also be made that it’s less effective for catching errors due to its relative permissiveness and opt-in behavior.

There is no clear winner between the two and context is what matters. TypeScript may be better suited for more enterprise projects with a long support horizon, also by considering that in such a project developers can make use of its more advanced features. Flow may be a better choice for leaner projects, or as a way to introduce type checking into an already existing project without it being too painful. It’s up to you to decide which tool best suits your project and circumstances.

But before doing so, it’s worth expanding on the subject of community size between the two. This impacts how easy it is to find developers having experience with these tools, which can make the staffing process simpler (or more challenging) based on what experience you’re looking for.

TypeScriptFlow
Stars61.1k20.7
Used By2.1m75.5k
Pull Requests192135
Issues45712422
Contributors486689

We can clearly see that TypeScript is more popular than Flow. It’s also worth noting that Flow has a relatively high number of pull requests and issues given its utilization in comparison to TypeScript. This could potentially indicate that the Flow team is less effective at managing bugs and change requests for the project, or it could just be a statistical blip.

Now let’s compare downloads via npm:

chart comparing number of downloads for typescript vs flow in 2022
Chart comparing the total NPM downloads of Flow and TypeScript

Again we see TypeScript’s popularity vs Flow over the last year. It’s also worth noting the clear upward trend in TypeScript downloads. It looks like Flow may be at the start of a decrease in utilization as well.

If you’re wondering why there’s such a dip around year-end 2019, it’s a pattern seen across all package managers as developers are less active during that period due to holidays, both for professional and personal projects.

We can also compare the tags of both tools on Stackoverflow to have an idea of how likely it is to find an answer to a potential problem. For the [TypeScript] tag we can see that there are about 116.8k questions about TypeScript, and on the other hand, for the [flowtype] tag, we can see that there are about 2.2k questions. This is another indication that TypeScript has a bigger community than Flow and that it’s more likely to have a question answered on the topic. However, I supposed one could make an argument that because Flow is so lightweight and straightforward, it doesn’t create an active discussion on sites like Stack Overflow, which is typically used by those experiencing problems with a piece of technology while looking for solutions.

Flow or TypeScript?

There are clear differences between both TypeScript and Flow. With respect to functionality, TypeScript is more robust, while Flow is simply a type checker – and potentially all you need if type checking and the related reduction in errors is your main goal. Although Flow is created by Facebook – the creators of React – its framework-agnostic nature (much like TypeScript’s) provides no significant benefits specifically for React, beyond a similar design philosophy.

When choosing one over the other, for those concerned with community and a long-term support horizon, TypeScript would seem to be a better choice. Conversely, for those seeking a lightweight and more accessible approach, Flow is worth taking a look at.

When it comes to staffing a project, it seems clear that it will be much easier to find TypeScript developers given its popularity when compared to Flow js. When sourcing for a Flow project, given its ease of use, it’s likely safe to say that most developers could pick it up on the fly. However, due to the learning curve of TypeScript, it may be desirable to find developers with previous experience so that a project is able to move quickly.


Key Takeaways

Is Flow faster than TypeScript?

In general, TypeScript is faster than Flow when it comes to performance. Flow is quicker to start using in a project, as it only requires you to add an annotation to a regular JavaScript file. For efficiency, TypeScript is the best choice. For getting up and running quickly, Flow tends to be a better choice.

Is Flow better than TypeScript?

This greatly depends on the use case and preferences of the developer. TypeScript has a number of cons, including a steep learning curve and boilerplate code, however, TypeScript also offers a large community and additional functionality. Flow is generally less robust with a smaller community, but offers a better ease of use.

What is the difference between Flow and TypeScript?

TypeScript provides more than just type checking when it’s added to a project. Flow primarily provides type-checking functionality. TypeScript has a steeper learning curve compared to Flow but offers more robustness as a result. Generally, Flow is a simple type checker, whereas TypeScript is a more complex type checker that also extends JavaScript functionality.

Looking to hire?

Join our newsletter

Join thousands of subscribers already getting our original articles about software design and development. You will not receive any spam, just great content once a month.

 

Read Next

Browse Our Blog