TypeScript

If you are in the front-end software development, chances are that you've heard and worked with TypeScript, a typed superset of JavaScript created and maintained by Microsoft. The idea behind this superset is strengthening the large-scale application development on the front-end and, as a programming language, it is designed to enhance JavaScript by enabling strong types. After all, its name speaks for itself.

The static typing is optional, but this is what's all about. It's the feature that we have in many server-side languages like Java or C#. Static typing can provide many advantages and helps compiler to better understand the code you are writing. It helps us to find errors with more accuracy, improves the documentation process, ensures that each variable we define receives the correct value.

It encapsulates the ECMAScript syntax, meaning that we can use class, module, const, let and all other neat things coming from it, and not only that, it takes us one step further by providing the features that are not provided natively by the ECMAScript. This includes features like generics, decorators...etc. It has a pretty big community behind it, meaning that it might be the option with the best support when it comes to writing static JavaScript. Also, it enables us to type our code without changing it by creating the declaration files, which is neat.

Flow

Flow, on the other hand, was developed by Facebook and it IS NOT a programming language by itself, but rather a Static Type Checker as defined on the official documentation website. Being dynamic as it is, JavaScript can cause a lot of troubles when it comes to the program output, meaning that programmers get the non-desired result at the end. In it, we can define a variable with the initial value set to a string value and latter, purposely or NOT (usually not, that's why this is bolded :)) assign an integer value to it and the compiler will not throw an error. Here flow comes into play. It's easily integrated with the JavaScript code with a simple comment annotation. All we need to do, after installing an configuring it, is to add a single line of code:

// @flow

at the beginning of the JavaScript file. It cannot be simpler than this.

Another good thing is that Flow is incrementally adoptable and it can be easily added and removed from our code base without breaking anything. This is good for situations when we, for example, want to enable type checking for only one part of our project.

Comparison

I will try to annotate the key differences and similarities between the two with the list below:

JavaScript Background

TypeScript Flow
A typed superset of the JavaScript language. It's a programming language of its own built to provide features missing in the JavaScript like static typing A JavaScript type checker that lives on top of our existing JS code. Built to enable fast and precise code analysis.

Benefits

TypeScript Flow
It offers static typing as the key benefit. Besides that, it provides useful tools like code refactoring, auto-completion, navigation. It has great IDE support. Its integration with VSCode made the editor so popular. It offers static typing as the key benefit. Also, it provides a strong procedural analysis and it strongly understands the code it should analyze and control.

Features

TypeScript Flow
Compile time type validation (it will not allow the app to compile properly if the typing is incorrect); Type annotations; Enumerations; Decorators; Generics; Interfaces; Namespaces; Modules; JSX; Definition files; Type checking JS files (@ts-check for example) Static type checking; Type annotations; Generics; Interfaces; Code rechecking upon any change (Real-time feedback); Precise; Fast; Easy integration; Strong understanding of JavaSCript patterns;

Advantages

TypeScript Flow
Popular frameworks support (Vue, React, Angular); Strong community; Existence of declaration files for a majority of JS libraries; Strong IDE support; Check JS files without changing them (declaration files); Support for any JS file; Easy to integrate; Strong understanding of the JS patterns; Not a programming language; Real-time feedback; Speed; Precision

Disadvantages

TypeScript Flow
Another programming language; Harder to integrate with the existing JS projects; Smaller community; Not so focused on the types; Smaller IDE support
TypeScript Flow
Support for all major frameworks, Vue, Angular and React therefore we can use TypeScript with any of them Advanced, built-in support for React meaning that Flow might be a better choice when React is our target framework.

Community Support

This is an important section for each product. The amount of support a product gets from the users directly dictates its survival. If we do the math here, we can conclude that the older, more polished TypeScript has a strong community behind it. On the other hand, Flow is younger thus the community support is lacking (although, community support does not depend only on the product age).

TypeScript enjoys the Angular 2+ full support, meaning that there is an established ecosystem around the integration. A strong community makes us less worried that we won't be able to use the desired tool in our project because someone probably has written a TS declaration file for the tool. Also, we have a great IDE based on it (VSCode) which I believe that it owes its popularity to the TypeScript. The performance is great, at least I didn't encounter any problems on my projects.

With Flow, we have a different situation. It's a younger project with a smaller community supporting it, but we cannot disacknowledge that it has a fair amount of stars on the official GitHub page. The smaller community means fewer library definitions thus we should be careful and make sure that our project doesn't (and will not in the future) require an unsupported library. Predictions are important and this can be a tricky thing if you lack experience as a developer therefore extra care is required when choosing a tool for our project. A great thing is that Flow has strong built-in support for React which means that as long React maintain its popularity and the integration remains strong, Flow will have a secure future I believe.

Syntax Comparison

In the comparison below, we will compare some of the common use cases. For more details check out this repo.

Nullable Type

TypeScript

let myVariable: string | null | undefined

Flow

In Flow, we can do it like this:

let myVariable: : ?string

// the above statement is equivalent to:

let myVariable: : string | null | void

Optional Parameters

TypeScript

We can define an optional parameter by specifying its name which is followed by the question mark (?) right before the : sign.

function fullName(firstName: string, lastName?: string) {
    return lastName ? firstName + " " + lastName : firstName;
}

Any optional parameters must follow the required parameters. Had we wanted to make the first name optional, rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list.

Flow

With Flow, it's a bit different. The question mark (?) goes after the : sign:

function fullName(firstName: string, lastName: ?string) {
  return lastName ? firstName + " " + lastName : firstName;
}

Casting

TypeScript

let a: any = "1";
let b = a as number;

// the value itself can be cast as well

(1 + 1) as number;

Flow

let a: any = "1";
let b = (a: number);

// the value itself can be cast as well

(1 + 1 : number);

Type cast expressions can appear anywhere an expression can appear.

Modules

It is often useful to share types between modules (files). In both of our tools, we can export type aliases, interfaces, and classes from one file and import them in another.

TypeScript

class MyClass {};

export default MyClass;
export { MyClass };
export { MyClass as someName };

Import:

// Import a single export from a module
import { MyClass } from "MyClass";

// Import the entire module

import * as MyClass from "MyClass";

Flow

Exports:

export default class MyClass {};
export type MyObject = { /* ... */ };
export interface MyInterface { /* ... */ };

Imports

import type MyClass, { MyObject, MyInterface }

In Flow, when importing a class we need to use the type keyword.

Which is better for React based project?

At the end of our comparison, let us consider the React support and how well they integrate with this framework. Considering that Flow was built by the same company (Facebook) like React we can expect it to be the right tool for the React based projects. We are not far from the truth. Here is where Flow can show its full potential. It has strong, built-in support for React. You will be glad to hear that, if you are a fan of create-react-app command, it supports Flow by default. All you need to do is install Flow and create a .flowconfig file by running flow init. Check out this guide.

TypeScript on the other hand in the past had a slightly worse React support but this is no longer the case. Now it has a built-in JSX support. In order for us to use this feature, we need to name our files with the tsx extension and enable the JSX option in the tsconfig file. This means that poor React support is behind us. Check out the official jsx guide.

Conclusion

I think that both of our tools have reached a stage where is totally valuable to use it. It's a matter of preferences and what works for you might not work for me, therefore it may come naturally for us to pick the different tool for the job. Personally, I've used TypeScript on the majority of my projects and I'm happy with it. If you seek deeper integration with React, and you think TypeScript is lacking it, then Flow is your pick. If you think this article helped you, share it or follow me on twitter :)

Resources

  1. TypeScript official docs
  2. Flow official docs
  3. GiHub comparison repo

Further Reading

Check out this article where I did a Hello World comparison of React, Vue, and PlazarJS