Photo by m0851 on Unsplash

Linting in Flow

Roger Ballard
Flow

--

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:

Let’s fix that, shall we?

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

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();

How about another example?

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

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!

--

--