Lint Rule Reference
all
While all
isn't technically a lint rule, it's worth mentioning here. all
sets the default
level for lint rules that don't have a level set explicitly. all
can only
occur as the first entry in a .flowconfig
or as the first rule in a --lints
flag. It's not allowed in comments at all because it would have different
semantics than would be expected.
ambiguous-object-type
Triggers when you use object type syntax without explicitly specifying exactness or inexactness.
This lint setting is ignored when exact_by_default
is set to false
.
1// flowlint ambiguous-object-type:error2
3type A = {x: number}; // Error 4type B = {x: number, ...} // Ok5type C = {| x: number |} // Ok
3:10-3:20: Please write this object type as explicitly exact (use `{|` and `|}` instead of `{` and `}`) or as explicitly inexact (add `...` to the end of the list of properties). [ambiguous-object-type]
deprecated-type
Triggered on the bool
type, which is just an alias for boolean
. Just use boolean
instead.
1// flowlint deprecated-type:error 2
3type A = Array<bool>; // Error
1:13-1:33: Redundant argument. This argument doesn't change any lint settings. [lint-setting]3:16-3:19: Deprecated type. Use `boolean` instead. [deprecated-type]
implicit-inexact-object
Like ambiguous-object-type
, except triggers even when the exact_by_default
option is set to false
.
nonstrict-import
Used in conjuction with Flow Strict. Triggers when importing a non @flow strict
module. When enabled, dependencies of a @flow strict
module must also be @flow strict
.
sketchy-null
Triggers when you do an existence check on a value that can be either null/undefined or falsey.
For example:
1// flowlint sketchy-null:error2
3const x: ?number = 5;4if (x) {} // sketchy because x could be either null or 0. 5
6const y: number = 5;7if (y) {} // not sketchy because y can't be null, only 0.8
9const z: ?{foo: number} = {foo: 5};10if (z) {} // not sketchy, because z can't be falsey, only null/undefined.
4:5-4:5: Sketchy null check on number [1] which is potentially 0. Perhaps you meant to check for null or undefined [2]? [sketchy-null-number]
Setting sketchy-null
sets the level for all sketchy null checks, but there are more granular rules for particular types. These are:
sketchy-null-bool
sketchy-null-number
sketchy-null-string
sketchy-null-mixed
sketchy-null-bigint
The type-specific variants are useful for specifying that some types of sketchy null checks are acceptable while others should be errors/warnings. For example, if you want to allow boolean sketchy null checks (for the pattern of treating undefined optional booleans as false) but forbid other types of sketchy null checks, you can do so with this .flowconfig
[lints]
section:
[lints]
sketchy-null=warn
sketchy-null-bool=off
and now
function foo (bar: ?bool): void {
if (bar) {
...
} else {
...
}
}
doesn't report a warning.
Suppressing one type of sketchy null check only suppresses that type, so, for example
1// flowlint sketchy-null:error, sketchy-null-bool:off2const x: ?(number | bool) = 0; 3if (x) {}
2:21-2:24: Deprecated type. Use `boolean` instead. [deprecated-type]3:5-3:5: Sketchy null check on number [1] which is potentially 0. Perhaps you meant to check for null or undefined [2]? [sketchy-null-number]
would still have a sketchy-null-number
error on line 3.
sketchy-number
Triggers when a number
is used in a manner which may lead to unexpected results if the value is falsy.
Currently, this lint triggers if a number
appears in:
- the left-hand side of an
&&
expression.
As a motivating example, consider this common idiom in React:
{showFoo && <Foo />}
Here, showFoo
is a boolean which controls whether or not to display the <Foo />
element. If showFoo
is true, then this evaluates to {<Foo />}
. If showFoo
is false, then this evaluates to {false}
, which doesn't display anything.
Now suppose that instead of a boolean, we have a numerical value representing, say, the number of comments on a post. We want to display a count of the comments, unless there are no comments. We might naively try to do something similar to the boolean case:
{count && <>[{count} comments]</>}
If count
is, say, 5
, then this displays "[5 comments]". However, if count
is 0
, then this displays "0" instead of displaying nothing. (This problem is unique to number
because 0
and NaN
are the only falsy values which React renders with a visible result.) This could be subtly dangerous: if this immediately follows another numerical value, it might appear to the user that we have multiplied that value by 10! Instead, we should do a proper conditional check:
{count ? <>[{count} comments]</> : null}
unclear-type
Triggers when you use any
, Object
, or Function
as type annotations. These
types are unsafe.
1// flowlint unclear-type:error2
3declare const a: any; // Error 4declare const c: Object; // Error 5declare const d: Function; // Error
3:18-3:20: Unclear type. Using `any`, `Object`, or `Function` types is not safe! [unclear-type]4:18-4:23: Unclear type. Using `any`, `Object`, or `Function` types is not safe! [unclear-type]5:18-5:25: Unclear type. Using `any`, `Object`, or `Function` types is not safe! [unclear-type]
unnecessary-invariant
Triggers when you use invariant
to check a condition which we know must be truthy based on the available type information. This is quite conservative: for example, if all we know about the condition is that it is a boolean
, then the lint will not fire even if the condition must be true
at runtime.
Note that this lint does not trigger when we know a condition is always false
. It is a common idiom to use invariant()
or invariant(false, ...)
to throw in code that should be unreachable.
1// flowlint unnecessary-invariant:error2declare function invariant(boolean): void;3
4declare const x: Array<string>; // Array is truthy5invariant(x);
5:1-5:12: This use of `invariant` is unnecessary because array type [1] is always truthy. [unnecessary-invariant]
unnecessary-optional-chain
Triggers when you use ?.
where it isn't needed. This comes in two main flavors. The first is when the left-hand-side cannot be nullish:
1// flowlint unnecessary-optional-chain:error2type Foo = {3 bar: number4}5
6declare const foo: Foo;7foo?.bar; // Error
7:1-7:8: This use of optional chaining (`?.`) is unnecessary because `foo` [1] cannot be nullish or because an earlier `?.` will short-circuit the nullish case. [unnecessary-optional-chain]
The second is when the left-hand-side could be nullish, but the short-circuiting behavior of ?.
is sufficient to handle it anyway:
1// flowlint unnecessary-optional-chain:error2type Foo = {3 bar: {4 baz: number5 }6}7
8declare const foo: ?Foo;9foo?.bar?.baz; // Error
9:1-9:13: This use of optional chaining (`?.`) is unnecessary because `foo?.bar` [1] cannot be nullish or because an earlier `?.` will short-circuit the nullish case. [unnecessary-optional-chain]
In the second example, the first use of ?.
is valid, since foo
is potentially nullish, but the second use of ?.
is unnecessary. The left-hand-side of the second ?.
(foo?.bar
) can only be nullish as a result of foo
being nullish, and when foo
is nullish, short-circuiting lets us avoid the second ?.
altogether!
foo?.bar.baz;
This makes it clear to the reader that bar
is not a potentially nullish property.
unsafe-getters-setters
Triggers when you use getters or setters. Getters and setters can have side effects and are unsafe.
For example:
1// flowlint unsafe-getters-setters:error2let a = 1;3const o = {4 get a() { return a; }, // Error: unsafe-getters-setters 5 set b(x: number) { a = x; }, // Error: unsafe-getters-setters 6 c: 10,7};
4:3-4:23: Getters and setters can have side effects and are unsafe. [unsafe-getters-setters]5:3-5:29: Getters and setters can have side effects and are unsafe. [unsafe-getters-setters]
untyped-import
Triggers when you import from an untyped file. Importing from an untyped file
results in those imports being typed as any
, which is unsafe.
untyped-type-import
Triggers when you import a type from an untyped file. Importing a type from an
untyped file results in an any
alias, which is typically not the intended behavior.
Enabling this lint brings extra attention to this case and can help improve Flow
coverage of typed files by limiting the spread of implicit any
types.
unused-promise
Triggers when a Promise
is unused. This can be dangerous, because errors are potentially unhandled, and the code may not execute in the desired order.
A promise can be "used" by...
await
ing it- Calling
.then
with a rejection handler (i.e., with two arguments) - Calling
.catch
- Calling
.finally
- Storing it in a variable, passing it to a function, etc.
For example:
1// flowlint unused-promise:error2declare function foo(): Promise<void>;3
4async function bar() {5 await foo(); // ok6 foo(); // error, we forgot to await! 7}8
9function baz() {10 foo().catch(err => {console.log(err)}); // ok11 foo(); // error 12}
6:3-6:8: `Promise` in async scope is unused. Did you mean to `await` it? [unused-promise]11:3-11:8: `Promise` in sync scope is unused. Promises must be handled by calling .then with a rejection handler, .catch, or .finally. [unused-promise]
You can explicitly ignore the promise with the void
operator (e.g., void foo();
).
Note: As of v0.201.0, this rule subsumed the unused-promise-in-async-scope
and unused-promise-in-sync-scope
rules.