Skip to content

Instantly share code, notes, and snippets.

@matthargett
Created November 19, 2018 21:00
Show Gist options
  • Save matthargett/07804ef5dcaa7854bce76d53724bd57b to your computer and use it in GitHub Desktop.
Save matthargett/07804ef5dcaa7854bce76d53724bd57b to your computer and use it in GitHub Desktop.
TypeScript versus flowtype

First, let's note the difference in philosophy: TypeScript aims for fast analysis because you can to compile it down to JS before you can run/test it. flowtype is meant to be an async analysis that can run continuously with changes since the last analysis, or in parallel with your eslint and bundler rules. As such, flowtype's type system and analysis is not quite as concerned with speed or memory usage in service of potentially finding more bugs.

On two occasions I have tried to roll out flow in React Native applications, and on those two occasions we ended up backing out after a few weeks. Some detail: flow doesn't have a public roadmap, and what version you use is dictated by the react/react-native dependency and the annotations in react-native itself. flowtype also has some hard-coded aspects to help the analysis for React, so major updates to React itself sometimes also require updating flowtype to match. React Native upgrades then get gated based on your dependent libraries (or flow-typed) being updated as well: flow-typed/flow-typed#1857 (comment)

This is a cheat only Facebook can do, the rest of us have to duplicate our definitions and there's currently no way for one definition to depend on another. The reason this works at all for anyone is because Facebook has a monorepo in their deployment of flow, so packaging and versioning aren't issues for them: flow-typed/flow-typed#2842

Following both TypeScript and flow over the last two years, and talking with core committers to both, they are very competitive in terms of core type system and analysis features. One finds bugs the other doesn't, and vice versa. Both have the downside of being single-vendor solutions, and neither are managed by independent standards bodies. Neither has full support for variadic generics, which was a key type system feature for C++ and C#. TypeScript appears to be pushing back on this feature due to the compute required (read: build times) in common cases, whereas flowtype is making more progress. These kinds of features are less important for app developers, but more important for library developers.

Microsoft has published a spec for TypeScript under the Open Web Foundation, and has a reasonable history of merging code changes and some spec changes from third parties (50% contributors are external in the last month). So far they have hit all of the release dates for milestones in their roadmap over the last year. Both of their issue trackers and PRs are a mess with many, many open items. That being said, TypeScript has had 346 commits over the last month versus 291 for flowtype. The diversity of committers is roughly the same between them.

Since babel 7 is supposed to enable generation flowtype from TypeScript definitions, I feel that TypeScript is the better and more flexible choice for developer experience and bug-finding. Developers can get near-instant feedback as they type in their IDE without draining battery life or using gigabytes of RAM, and we can do flowtype checks (and minor manual) annotations as-needed to cover the gaps in TypeScript analysis. There are currently blockers with TypeScript, (like babel/babel#8244 (comment) ) but I feel we have a better chance of contributing/funding the changes we need in babel and TypeScript versus flowtype and flow-typed.

I've only really come around to TypeScript being the practical option in the last few months after deep discussion with my colleagues and the community. I hope laying out my reconciliation process helps others, whatever the decision people make are.

@jamonholmgren
Copy link

Thanks for writing this up, Matt!

@GantMan
Copy link

GantMan commented Nov 20, 2018

Great analysis. TypeScript + Flow is such a cool concept. I'd love to read more about the known gaps you're filling and if you find a good way to get everyone to play nicely. Please write more, this was great!

@DanielHoffmann
Copy link

DanielHoffmann commented Nov 20, 2018

From my understanding Flow can be automatically converted to plain JS (you do lose proptypes for react components though) while Typescript can not. So there is little effort to start a project with Flow and remove it later if the advantages don't pan out to be worth it. That reason alone should be enough to convince people that are on the fence about it.

FYI I never tried to actually convert a Flow codebase to plain JS so I might be wrong with my statements

@jmcginty
Copy link

Thanks for sharing your experiences Matt, we use TypeScript for RN and find it works really well

@piuccio
Copy link

piuccio commented Nov 21, 2018

Great insight, I started with Flow because it lets you annotate files with comments. When I write code for node.js (server) I want types but don't want to add another compilation step; nodemon works just fine with flow inside comments. Typescript doesn't let you do that as far as I know.
I've now adopted flow type for react native projects because it just works (at least with RN0.57) but the main pain point is that react and react-types are not always in sync. Things like .forwardRef or other 'new' APIs have not been implemented in flow type so I either define the types myself or use // $FlowFixMe.
Another pain point is that flow type with atom breaks the syntax highlight when using generics on function calls gandm/language-babel#508 and I don't think it'll be fixed soon; but maybe Atom is not the best editor when you use types...

@t7yang
Copy link

t7yang commented Nov 21, 2018

@piuccio

Typescript doesn't let you do that as far as I know.

sure you can, TypeScript can do much more
https://twitter.com/octref/status/1031677783808724992

@ashfurrow
Copy link

Great write-up. As someone who joined after the initial wave of flow-vs-ts discussions, it's nice to get a thorough and succinct briefing on the background of the subject. Thanks for taking the time to write this up.

@kumarharsh
Copy link

kumarharsh commented Nov 22, 2018

Thanks for the write-up. I have faced a few issues myself using flow which I'd like to document:

  1. I use VSCode running on Windows as my primary dev environment. And flow is absolutely unusable there. I believe none of the core maintainers work in Windows so many blocking issues which I and others have experienced from even 18 month's ago haven't been solved on the flow plugin. The flow team also started work on a languageserver implementation, but frustratingly that also doesn't work at all on Windows.
  2. There is no public timeline or roadmap for flow's future development or maintenance. You would never know if your issue is even on the maintainers radar.
  3. There is very less public communication in some flow repos, and probably a lot of it happens behind closed doors in phabricator within Facebook.
  4. Flow is written in OCaml. I thought about contributing to flow to see if maybe I could try fixing some issues or atleast understand why they happen, but was stunned to find that OCaml wasn't even supported on Windows. Things have changed recently, but there is still no stable way to run it I believe. Even the Ocaml for Windows project comes with the experimental tag.

I'm not criticizing any of the Flow mainteners here - they are really awesome in what they do and it's great that a thing like flow exists. Some of the concepts are much better than typescript and it's actually pretty fun to use it. But I have just grown to dislike the whole process under which flow is being developed. Microsoft's approach is leaps and bounds better in this case where everything is done publicly and issue/PR management is generally much better. Also for me, Typescript just works wherever I am working, but with flow it's yay for Linux and a gut-wrenching hard NO for Windows even after so many months.

@jhampton
Copy link

Thank you for laying out your thoughts, sir. I've had a gut feeling for the last few months (as you know) that TS has longer legs. I also think that, given its compile-first nature, there will be more opportunity for transpilation to other (read: more native) languages for myriad reasons.

Now I just need to redo a few months worth of publicity and work :)

@Bardiamist
Copy link

I using Flow beacuse React native using it internal. If React native switches to TypeScript then the choice will be obvious to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment