Errors encountered upgrading Flow v0.85

April 22, 2019


Despite seeing the JS community slowly moving away from Flow to TypeScript, Shopee Web Frontend codebase is still very much stuck with Flow. 😨

After some silence, Flow has come back and committed to be a more efficient, reliable and friendly tool. Thus, we decided to give Flow a final chance. However, in order to enjoy the improvements that Flow has made in recent days, we have to upgrade Flow from 0.83 (since our last update) to v0.97 (latest to date), which meant that we need to upgrade past v0.85, which meant hell to codebase that uses react-redux extensively.

One of our brave developer, Gao Wei took up the challenge and decided to bring us to the bright side of Flow. 😅. She twitted and wrote an article on how she fixed the errors arose in the process.

To put the problem in perspective, from Flow 0.85 onwards, Flow is asking for required annotations for implicit annotations. Or less technical, if you are trying to export something that was created from a generic class (eg: class Foo<T>) or functions (eg: function foo<T>(){}), without explicit type arguments (eg: new Foo<Type>() or foo<Type>()), Flow is going to give you an error.

Or in layman terms, if your repo is full of HOCs or connect(), you are f**ked. So, be sure the check Gao Wei's blog if you are one of the brave souls upgrading a Flow project.

The Tooling

In this article, I would like to list out some of the roadblocks we encountered that was less well discussed, the tooling for the latest Flow syntax, which is the TypeParameterInstantiation, eg: calling a function or instantiation a class with a type parameter, new Foo<Type>() or foo<Type>().

Babel & Eslint

We had to upgrade our babel to babel v7 and babel-eslint (a babel wrapper for eslint) to babel-eslint v9 to support this new syntax.

You can read about on how we came to realise the need of this upgrade in my previous post.

There was another interesting bug that we ran into regarding @babel/plugin-transform-flow-strip-types, you can read more on how we uncover it in my other blog post.


We had to upgrade prettier to v1.16.0 and use babel-flow parser for prettier to resolve the ambiguity in syntax arise in parsing the newer Flow syntax. In simpler terms, to tell Prettier that


is calling foobar with argument, 1 and type, "Type", instead of:

foobar < Type > 1

is the result of foobar < Type, greater than 1? 😂

You can read more about it in Prettier's blog post.


Flow Lazy Mode has been around since v0.68, but we hadn't enjoy the benefit of lazy mode through VSCode until recently.

Now we can specify lazyMode in our .vscode/settings.json:

  "flow.useLSP": true,
  "flow.lazyMode": "ide"

Although lazy mode reduces the scope where Flow does type checking, one of the pain point we had with Flow was to wait for Flow to do recheck, before returning a meaningful Flow status again. Flow team did some optimisation in v92.0, where it says:

This release culminates months of hard work on quality of life improvements for IDE support. Expect your requests to be faster, and your requests to take a bit less time.

According to the release note, Flow is now able to provide type definitions while rechecking, for further details on how they achieve this, you can read the Flow blog

Closing remarks

Finally we managed to get Flow running in v0.97 🎉. We've been struggling with bad developer experience with v0.83 for the longest time, hopefully v0.97 do not let us down.

Lastly, be sure to check out all the links sprinkled throughout this blog, they link to Github issues, commits, release notes, and who knows it might lead you to some unexpected adventures? 🤷‍

But if you are lazy like me, here are the links, they served as my references when writing this blog post: