Running Flow on existing code
A word of warning#
Making previously-untyped code typecheck with Flow may take some time and work - and sometimes it may not be worth the effort in the short term. Flow supports interface files so you can use libraries in a typed way without having to run Flow on them at all. If your project just depends on third party libraries, check out our guide on using Flow with external dependencies and consider using an interface file for the libraries.
Why is typechecking existing code so hard? Libraries not written with types in mind often contain complex, highly dynamic code that confuses analyzers such as Flow. The code may also have been written in a style that Flow deliberately chooses not to support in order to give the programmer more help. Some typical examples are:
- Operations on primitive values: While JavaScript allows operations such as
true + 3
, Flow considers it a type error. This is by design, and is done to provide the programmer with more safety. While that’s easily avoided for new code, it can sometimes be a lot of effort to eliminate such patterns from existing code. - Nullability: Flow protects you against accessing properties on
null
by tracking null or undefined values throughout the program. In large existing codebases, though, this can require inserting some extra null checks in places where a value appears like it may be null, but actually isn’t at runtime.
It is typically a much larger effort, and requires much more programmer annotation, to get such code to typecheck. On the other hand, if you own a library and would like to benefit from Flow typechecking within the library itself, this guide is for you.
Dealing with a large number of type errors#
If you encounter too many type errors after running Flow and don’t know how to
proceed, you could quickly cut down the number of type errors by adding the
any
type to parameters and returns of selected
functions in your code. This will have the effect of isolating type errors to
smaller regions of code - for example, within function bodies but not across
function calls - and making them more manageable and easier to fix.
This strategy should give you some benefit straight away without too much work. The typical errors you are likely to run into are:
- Potentially
null
orundefined
values, easily fixed by adding conditional checks. - Primitive type issues, like
true + 3
. Fixing these requires more knowledge of the code but is usually a small, local fix. - In cases where Flow just doesn’t understand the code as written, explicitly annotating values with
any
can help the typechecker.
Next steps#
Once your code typechecks after sufficient fixes and uses of the any
type, you
can start replacing any
with better type annotations incrementally. Each type
annotation you add will allow Flow to validate more code, and you can gradually
increase Flow’s coverage of your code.
You can edit this page on GitHub and send us a pull request!