Better Flow Error Messages for the JavaScript Ecosystem

Over the last year, the Flow team has been slowly auditing and improving all the possible error messages generated by the type checker. In Flow 0.66 we’re excited to announce a new error message format designed to decrease the time it takes you to read and fix each bug Flow finds.

Source: Dmitry Boldyrev
The images in this blog post are of Flow’s new CLI renderer, designed by Lee Byron. Lee graciously offered to design an updated CLI renderer when I introduced him to the new error message format.

What makes an error?

Flow’s type system is structural and allows for thorough type inference. Both of these properties make it difficult to write good error messages.

Because the type system is structural, an error can happen deep within a nested type. For instance:

function myFunction(o: {foo: {bar: Array<string>}}) {
// ...
}
const bar = [1, 2, 3];
myFunction({foo: {bar}});

In this example the myFunction call is incorrect. The number array elements are incompatible with the expected string array type of property bar of property foo. We can’t just point to the numbers and string type. Then we wouldn’t point to the true source of the error. The myFunction call.

Flow infers types by reading your code. If you make a mistake, Flow may misinterpret your intent and infer different types than you expect. Adding type annotations is a great way of telling Flow what you expect. Then Flow can give you better error messages explaining why your code doesn’t match your expectations.

Each error message will point to a “root” location (highlighted in red) and some number of reference locations (highlighted in blue). These reference locations may be turned into hyperlinks in an IDE.

Source: Addi Unnithan

What else changed about error messages?

  • When a union type or intersection type is incompatible, instead of showing every branch (like Flow used to) a “score” will be calculated for each branch on only the branches with the highest scores will be shown. This makes a big difference for Redux users with large union types for actions. Use the --show-all-branches flag to disable this behavior.
  • Fixed locations for a lot of messages that failed to point to the source of the error.
  • Many unrelated locations in library types are no longer included in the error message output. Importantly this means suppression comments ($FlowFixMe) which might have suppressed error messages for every use of a function or component are no longer possible.
Source: Bogdan Chadkin

IDE

After Flow 0.66 IDE error messages should be greatly improved now that Flow outputs a single sentence for each error message instead of a collection of sentence fragments. The growth of Flow’s usage in IDEs is partly what inspired this new format.

While IDEs will continue to work with their current Flow plugins, IDEs can now use the rich text format output by Flow and provide an even better user experience!

Passing the flag --json-version=2 to Flow will give you the new error message format encoded in a subset of markdown (documentation).

Source: Ben Clayton (Webstorm)

References

  • Elm pioneered “Compiler Errors for Humans” which was certainly an inspiration for this work.
  • A few weeks ago, Glow was released providing a better CLI renderer for the old Flow error message format.
  • Reason also dramatically improved the error messages returned by OCaml for their users.

Flow 0.66 includes a few more exciting changes for the IDE experience. Find the full changelog on GitHub.

See an error message you really like in your projects? We want to see it! Send a tweet to @flowtype and we’ll include your error message in this blog post.