Image for post
Image for post
Photo by m0851 on Unsplash

Linting in Flow

Roger Ballard
Aug 4, 2017 · 4 min read

In the past, Flow has had to make some tough decisions about what counts as a type error, and what we should surface in our analysis. Some things, like enforcing function call parameter counts, made the cut. Others, like erring when importing types from an untyped file, didn’t. With version 0.52 we’re rolling out the new Flow linter, creating a framework that lets us report things we find that aren’t soundness issues, and lets you decide which pieces of the analysis are relevant to you.

What is the Flow linter?

The Flow linter is a customizable framework for general static analysis. It enables us to create flow-sensitive, type-aware lint rules, to give you more information than you get from just Flow’s type errors. It’s opt-in at a very granular level, so you can get the information you care about and hide the information you don’t. Our vision is to unlock Flow’s type intelligence for use in static analysis beyond the correctness of your programs.

What isn’t the Flow linter?

We aren’t trying to replace ESLint or other AST-based JavaScript linters. We believe that they already have that area figured out. The Flow linter is instead meant to be a home for type-aware lints that leverage Flow’s existing analysis engine.

What does it look like in action?

Let’s take a look at a small example:

// @flowfunction square(x: ?number) {
if (x) {
return x * x;
} else {
return NaN;
}
}

This function takes a maybe number, then returns its square if it’s a number, otherwise it returns NaN. At least, that’s what it’s supposed to do. square(0) returns NaN! Let’s see what the linter has to say:

Image for post
Image for post

Let’s fix that, shall we?

// @flowfunction square(x: ?number) {
if (x != null) {
return x * x;
} else {
return NaN;
}
}
Image for post
Image for post
Image for post
Image for post

Much better.

Because we have access to all of Flow’s analysis, this works on inferred types, too!

// @flowfunction square(x) {
if (x) {
return x * x;
} else {
return NaN;
}
}
square(5);
square(0);
square();
Image for post
Image for post
Image for post
Image for post

How about another example?

// @flowimport type {Foo} from './untyped.js';// `Foo` is actually `any`!
Image for post
Image for post
Image for post
Image for post

Thanks to the linter, we aren’t surprised by hidden anys.

How can I use the Flow linter?

You can turn on Flow linting for your project by adding the following to your .flowconfig:

[lints]
all=warn
[options]
include_warnings=true

You’ll then start getting warnings about the things Flow finds that aren’t type errors. Some information you might find useful, and other information you might want to ignore. The Flow linter is highly configurable; for a more detailed tutorial on how to get the most out of it, check out the documentation.


The Flow team is always hard at work to extend and improve various aspects of Flow. Linting is one such initiative. We plan on adding more lints, but slowly and based on how much impact each lint will have on users’ experience with Flow.

We are always looking for more lint ideas. If you have an idea for a helpful lint that can leverage Flow’s type information leave a reply to this post on Medium and tweet it to flowtype. We want to hear about what you’re building and how we can help you build it better!

Flow

The official publication for the Flow static type checker…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store