eslint-plugin-ft-flow
Flowtype linting rules for ESLint.
This project was heavily based off the original flowtype eslint plugin, all credits go to the original maintainers. We duplicated the project with the intention of providing the flowtype community support and maintenance for people that continue to use flowtype.
Installation
npm install eslint-plugin-ft-flow eslint hermes-eslint --save-dev
yarn add -D eslint-plugin-ft-flow eslint hermes-eslint
pnpm add -D eslint-plugin-ft-flow eslint hermes-eslint
Configuration
- Set
parser
property to hermes-eslint
. - Add
plugins
section and specify ft-flow
as a plugin. - Enable rules.
{
"parser": "hermes-eslint",
"plugins": ["ft-flow"],
"rules": {
"ft-flow/boolean-style": [2, "boolean"]
},
"settings": {
"ft-flow": {
"onlyFilesWithFlowAnnotation": false
}
}
}
Shareable configurations
Recommended
This plugin exports a recommended configuration that enforces Flowtype best practices.
To enable this configuration use the extends
property in your .eslintrc
config file in place of the above suggested properties:
{
"extends": ["plugin:ft-flow/recommended"]
}
Babel parser
Alternatively, if you can't yet use hermes-eslint
, prior to version 3.0.0 ft-flow shipped a recommended config that used @babel/eslint-parser
which is still available under the "plugin:ft-flow/babel-parser"
extension.
Though it's recommended to switch to the recommended extension when possible as babel-parser
may be removed in a future version.
By default this config also comes preloaded with @babel/eslint-parser
which means for eslint to analyze your flow code it relies your babel config (babel.config.js
, .babelrc
, .babelrc.js
). You should already have this setup as part of running/testing your code but if you don't you can learn more here
See ESLint documentation for more information about extending configuration files.
Settings
onlyFilesWithFlowAnnotation
When true
, only checks files with a @flow
annotation in the first comment.
{
"settings": {
"ft-flow": {
"onlyFilesWithFlowAnnotation": true
}
}
}
Rules
array-style-complex-type
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces a particular annotation style of complex types.
Type is considered complex in these cases:
This rule takes one argument.
If it is 'verbose'
then a problem is raised when using Type[]
instead of Array<Type>
.
If it is 'shorthand'
then a problem is raised when using Array<Type>
instead of Type[]
.
The default value is 'verbose'
.
The following patterns are considered problems:
type X = (?string)[]
type X = (?string)[]
type X = Array<?string>
type X = Array<{foo: string}>
type X = (string | number)[]
type X = (string & number)[]
type X = [string, number][]
type X = {foo: string}[]
type X = (string => number)[]
type X = {
foo: string,
bar: number
}[]
type X = {
foo: string,
bar: number,
quo: boolean,
hey: Date
}[]
The following patterns are not considered problems:
type X = Array<?string>
type X = Array<?string>
type X = (?string)[]
type X = Array<string>
type X = Array<?string>
array-style-simple-type
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces a particular array type annotation style of simple types.
Type is considered simple in these cases:
This rule takes one argument.
If it is 'verbose'
then a problem is raised when using Type[]
instead of Array<Type>
.
If it is 'shorthand'
then a problem is raised when using Array<Type>
instead of Type[]
.
The default value is 'verbose'
.
The following patterns are considered problems:
type X = string[]
type X = string[]
type X = Array<string>
type X = Date[]
type X = Promise<string>[]
type X = $Keys<{foo: string}>[]
type X = any[]
type X = mixed[]
type X = void[]
type X = null[]
type X = Promise<{
foo: string,
bar: number
}>[]
type X = Promise<{
foo: string,
bar: number,
quo: boolean
}>[]
The following patterns are not considered problems:
type X = Array<string>
type X = Array<string>
type X = string[]
type X = Array<Array<string>>
type X = (?string)[]
type X = string[]
type X = Array
type X = typeof Array
arrow-parens
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces the consistent use of parentheses in arrow functions.
This rule has a string option and an object one.
String options are:
"always"
(default) requires parens around arguments in all cases."as-needed"
enforces no braces where they can be omitted.
Object properties for variants of the "as-needed"
option:
"requireForBlockBody": true
modifies the as-needed rule in order to require parens if the function body is in an instructions block (surrounded by braces).
The following patterns are considered problems:
a => {}
a => a
a => {
}
a.then(foo => {});
a.then(foo => a);
a(foo => { if (true) {}; });
a(async foo => { if (true) {}; });
(a) => a
(a,) => a
async (a) => a
async(a) => a
a => {}
(a) => a
async a => {}
async (a) => a
async(a) => a
The following patterns are not considered problems:
() => {}
(a) => {}
(a) => a
(a) => {
}
a.then((foo) => {});
a.then((foo) => { if (true) {}; });
a.then(async (foo) => { if (true) {}; });
() => {}
(a) => {}
(a) => a
(a) => {
}
a.then((foo) => {});
a.then((foo) => { if (true) {}; });
a.then(async (foo) => { if (true) {}; });
() => {}
a => {}
a => a
([a, b]) => {}
({ a, b }) => {}
(a = 10) => {}
(...a) => a[0]
(a, b) => {}
async ([a, b]) => {}
async (a, b) => {}
(a: T) => a
(a): T => a
() => {}
a => a
([a, b]) => {}
([a, b]) => a
({ a, b }) => {}
({ a, b }) => a + b
(a = 10) => {}
(...a) => a[0]
(a, b) => {}
a => ({})
async a => ({})
async a => a
(a: T) => a
(a): T => a
<T>(a: T) => a
<T>(a: T) => { return a; }
<T>(a: T) => { return a; }
<T>(a: T) => { return a; }
(a): %checks => typeof a === "number"
boolean-style
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces a particular style for boolean type annotations. This rule takes one argument.
If it is 'boolean'
then a problem is raised when using bool
instead of boolean
.
If it is 'bool'
then a problem is raised when using boolean
instead of bool
.
The default value is 'boolean'
.
The following patterns are considered problems:
type X = bool
type X = bool
type X = boolean
The following patterns are not considered problems:
type X = boolean
type X = boolean
type X = bool
type X = bool
define-flow-type
@deprecated rule that is no longer needed with the current recommended config but kept around in case people want to continue using it with @babel/eslint-parser
such as the babel-parser
extension.
Marks Flow type identifiers as defined.
Used to suppress no-undef
reporting of type identifiers.
The following patterns are not considered problems:
var a: AType
var a: AType; var b: AType
var a; (a: AType)
var a: AType<BType>
type A = AType
declare type A = number
opaque type A = AType
function f(a: AType) {}
function f(a: AType.a) {}
function f(a: AType.a.b) {}
function f(a): AType {}; var a: AType
function f(a): AType {}
class C { a: AType }
class C { a: AType.a }
class C { a: AType.a.b }
class C implements AType {}
declare interface A {}
({ a: ({b() {}}: AType) })
type X = {Y<AType>(): BType}
type Foo = $ReadOnly<{}>
enum Status { Active, Paused }
enum Status { Active = 'active', Paused = 'paused' }
enum Status { Active = 1, Paused = 2 }
var a: AType
var a: AType; var b: AType
var a; (a: AType)
var a: AType<BType>
type A = AType
declare type A = number
opaque type A = AType
function f(a: AType) {}
function f(a: AType.a) {}
function f(a: AType.a.b) {}
function f(a): AType {}; var a: AType
function f(a): AType {}
class C { a: AType }
class C { a: AType.a }
class C { a: AType.a.b }
class C implements AType {}
declare interface A {}
({ a: ({b() {}}: AType) })
type X = {Y<AType>(): BType}
type Foo = $ReadOnly<{}>
enum Status { Active, Paused }
enum Status { Active = 'active', Paused = 'paused' }
enum Status { Active = 1, Paused = 2 }
delimiter-dangle
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent use of trailing commas in Object and Tuple annotations.
This rule takes three arguments where the possible values are the same as ESLint's default comma-dangle
rule:
- The first argument is for Object and Tuple annotations. The default value is
'never'
. - The second argument is used for Interface annotations. This defaults to the value of the first argument.
- The third argument is used for inexact object notation (trailing
...
). The default value is 'never'
.
If it is 'never'
then a problem is raised when there is a trailing comma.
If it is 'always'
then a problem is raised when there is no trailing comma.
If it is 'always-multiline'
then a problem is raised when there is no trailing comma on a multi-line definition, or there is a trailing comma on a single-line definition.
If it is 'only-multiline'
then a problem is raised when there is a trailing comma on a single-line definition. It allows, but does not enforce, trailing commas on multi-line definitions.
The following patterns are considered problems:
type X = { foo: string, }
type X = { foo: string, }
type X = { foo: string; }
type X = {
foo: string,
}
type X = { foo: string }
type X = {
foo: string
}
type X = { foo: string, }
type X = {
foo: string
}
type X = { foo: string; }
interface X { foo: string; }
type X = { [key: string]: number, }
type X = { [key: string]: number }
type X = { [key: string]: number, }
type X = {
[key: string]: number
}
type X = { [key: string]: number; }
type X = { [key: string]: number, foo: string, }
type X = {
[key: string]: number,
foo: string,
}
type X = {
[key: string]: number,
aReallyLongPropertyNameHere: string,
}
type X = { [key: string]: number, foo: string }
type X = {
[key: string]: number;
foo: string
}
type X = { [key: string]: number, foo: string, }
type X = {
[key: string]: number,
foo: string
}
type X = { [key: string]: number, foo: string, }
type X = { foo: string, [key: string]: number, }
type X = {
foo: string,
[key: string]: number,
}
type X = {
aReallyLongPropertyNameHere: string,
[key: string]: number,
}
type X = { foo: string, [key: string]: number }
type X = { foo: string; [key: string]: number }
type X = { foo: string, [key: string]: number; }
type X = {
foo: string,
[key: string]: number
}
type X = { foo: string, [key: string]: number; }
type X = { ..., }
type X = { ...; }
type X = { ..., }
type X = { ...; }
type X = { ... }
type X = { ..., }
type X = { ...; }
type X = { ..., }
type X = { ...; }
type X = {
...,
}
type X = {
...;
}
type X = {
...,
}
type X = {
...;
}
type X = {
...
}
type X = {
...
}
type X = { foo: string, ..., }
type X = { foo: string; ...; }
type X = { foo: string, ..., }
type X = { foo: string; ...; }
type X = { foo: string, ... }
type X = { foo: string, ..., }
type X = { foo: string; ...; }
type X = { foo: string, ..., }
type X = { foo: string; ...; }
type X = {
foo: string,
...,
}
type X = {
foo: string;
...;
}
type X = {
foo: string,
...,
}
type X = {
foo: string;
...;
}
type X = {
foo: string,
...
}
type X = {
foo: string,
...
}
type X = { [key: string]: number, ..., }
type X = { [key: string]: number; ...; }
type X = { [key: string]: number, ..., }
type X = { [key: string]: number; ...; }
type X = { [key: string]: number, ... }
type X = { [key: string]: number, ..., }
type X = { [key: string]: number; ...; }
type X = { [key: string]: number, ..., }
type X = { [key: string]: number; ...; }
type X = {
[key: string]: number,
...,
}
type X = {
[key: string]: number;
...;
}
type X = {
[key: string]: number,
...,
}
type X = {
[key: string]: number;
...;
}
type X = {
[key: string]: number,
...
}
type X = {
[key: string]: number,
...
}
type X = [string, number,]
type X = [string, number,]
type X = [
string,
number,
]
type X = [string, number]
type X = [
string,
number
]
type X = [string, number,]
type X = [
foo, string
]
type X = [ number, string, ]
The following patterns are not considered problems:
type X = { foo: string }
type X = { foo: string }
type X = { foo: string, }
type X = { foo: string; }
type X = {
foo: string
}
type X = {
foo: string,
}
type X = { foo: string }
type X = {
foo: string,
}
type X = {
foo: string;
}
type X = { foo: string }
type X = {
foo: string
}
type X = {
foo: string,
}
type X = {
foo: string;
}
interface X { foo: string; }
type X = {}
type X = {}
type X = {}
type X = {}
type X = { [key: string]: number }
type X = { [key: string]: number, }
type X = { [key: string]: number; }
type X = { [key: string]: number }
type X = {
[key: string]: number,
}
type X = {
[key: string]: number,
}
type X = {
[key: string]: number
}
type X = { [key: string]: number }
type X = { [key: string]: number, foo: string }
type X = { [key: string]: number, foo: string, }
type X = { [key: string]: number; foo: string; }
type X = { [key: string]: number, foo: string }
type X = {
[key: string]: number,
foo: string,
}
type X = {
[key: string]: number,
foo: string,
}
type X = {
[key: string]: number;
foo: string
}
type X = { [key: string]: number, foo: string }
type X = { foo: string, [key: string]: number }
type X = { foo: string, [key: string]: number, }
type X = { foo: string; [key: string]: number; }
type X = { foo: string, [key: string]: number }
type X = {
foo: string,
[key: string]: number,
}
type X = {
foo: string,
[key: string]: number,
}
type X = {
foo: string;
[key: string]: number
}
type X = { foo: string, [key: string]: number }
type X = { ... }
type X = { ... }
type X = { ..., }
type X = { ... }
type X = { ... }
type X = {
...
}
type X = {
...
}
type X = {
...,
}
type X = {
...;
}
type X = {
...,
}
type X = {
...;
}
type X = {
...
}
type X = {
...,
}
type X = {
...;
}
type X = { foo: string, ... }
type X = { foo: string, ... }
type X = { foo: string, ..., }
type X = { foo: string; ...; }
type X = { foo: string, ... }
type X = { foo: string, ... }
type X = {
foo: string,
...
}
type X = {
foo: string,
...
}
type X = {
foo: string,
...,
}
type X = {
foo: string;
...;
}
type X = {
foo: string,
...,
}
type X = {
foo: string;
...;
}
type X = {
foo: string,
...
}
type X = {
foo: string,
...,
}
type X = {
foo: string,
...;
}
type X = { [key: string]: number, ... }
type X = { [key: string]: number, ..., }
type X = { [key: string]: number; ...; }
type X = { [key: string]: number, ... }
type X = { [key: string]: number, ... }
type X = {
[key: string]: number,
...
}
type X = {
[key: string]: number,
...,
}
type X = {
[key: string]: number;
...;
}
type X = {
[key: string]: number,
...,
}
type X = {
[key: string]: number;
...;
}
type X = {
[key: string]: number,
...
}
type X = {
[key: string]: number,
...,
}
type X = {
[key: string]: number;
...;
}
type X = [string, number]
type X = [string, number]
type X = [
string,
number
]
type X = [string, number,]
type X = [
string,
number,
]
type X = [ foo, string ]
type X = [
foo, string,
]
type X = [ number, string ]
type X = [
number,
string
]
type X = [
number,
string,
]
type X = []
type X = []
type X = []
type X = []
enforce-line-break
This rule enforces line breaks between type definitions.
The following patterns are considered problems:
type baz = 6;
const hi = 2;
const foo = 6;
type hi = 2;
const som = "jes";
type fed = "hed";
type som = "jes";
const fed = "hed";
type hello = 34;
const som = "jes";
type fed = "hed";
const a = 5;
export type hello = 34;
const a = 5;
export type hello = 34;
const a = 5;
type hello = 34;
The following patterns are not considered problems:
type gjs = 6;
type gjs = 6;
type hi = 2;
type X = 4;
const red = "serpent";
console.log("hello");
type Y = string | number;
type snooze = "dreaming" | "";
type Props = {
accountBalance: string | number,
accountNumber: string | number,
};
const x = 4;
const y = 489;
type Props = {
accountBalance: string | number,
accountNumber: string | number,
};
type RoadT = "grass" | "gravel" | "cement";
type A = string
enforce-suppression-code
This rule enforces a suppression code on flow suppression comments such as $FlowFixMe
and $FlowExpectedError
.
The following patterns are considered problems:
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
{ }
The following patterns are not considered problems:
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
generic-spacing
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent spacing within generic type annotation parameters.
This rule takes one argument. If it is 'never'
then a problem is raised when there is a space surrounding the generic type parameters. If it is 'always'
then a problem is raised when there is no space surrounding the generic type parameters.
The default value is 'never'
.
The following patterns are considered problems:
type X = Promise< string>
type X = Promise< string>
type X = FooBar<string >
type X = Promise< string >
type X = Promise< (foo), bar, (((baz))) >
type X = Promise<string >
type X = FooBar< string>
type X = Promise<string>
type X = Promise<(foo), bar, (((baz)))>
type X = FooBar< string >
type X = FooBar< string >
type X = Promise< (foo), bar, (((baz))) >
The following patterns are not considered problems:
type X = Promise<string>
type X = Promise<(string)>
type X = Promise<(foo), bar, (((baz)))>
type X = Promise<
(foo),
bar,
(((baz)))
>
type X = Promise<
(foo),
bar,
(((baz)))
>
type X = Promise< string >
type X = Promise< (string) >
type X = Promise< (foo), bar, (((baz))) >
interface-id-match
Enforces a consistent naming pattern for interfaces.
Options
This rule requires a text RegExp:
{
"rules": {
"ft-flow/interface-id-match": [
2,
"^([A-Z][a-z0-9]*)+Type$"
]
}
}
'^([A-Z][a-z0-9]*)+Type$'
is the default pattern.
The following patterns are considered problems:
interface foo{};
interface FooType{};
The following patterns are not considered problems:
interface FooType {};
interface foo {};
interface foo {};
newline-after-flow-annotation
This rule requires an empty line after the Flow annotation.
Options
The rule has a string option:
"always"
(default): Enforces that @flow
annotations be followed by an empty line, separated by newline (LF)"always-windows"
: Identical to "always", but will use a CRLF when autofixing"never"
: Enforces that @flow
annotations are not followed by empty lines
{
"rules": {
"ft-flow/newline-after-flow-annotation": [
2,
"always"
]
}
}
The following patterns are considered problems:
import Foo from './foo';
import Foo from './foo';
import Foo from './foo';
const text: string = 42;
The following patterns are not considered problems:
import Foo from './foo';
import Foo from './foo';
import Foo from './foo';
const text: string = 42;
no-dupe-keys
Checks for duplicate properties in Object annotations.
This rule mirrors ESLint's no-dupe-keys rule.
{
"rules": {
"ft-flow/no-dupe-keys": 2
}
}
The following patterns are considered problems:
type f = { a: number, b: string, a: number }
type f = { a: number, b: string, a: string }
type f = { get(key: "a"): string, get(key: "a"): string }
type f = { get(key: 1): string, get(key: 1): string }
type f = { get(key: 1.1): string, get(key: 1.1): string }
type f = { get(key: true): string, get(key: true): string }
type f = { get(key: {a: 1}): string, get(key: {a: 1}):string }
var a = "a"; type f = { get(key: a): string, get(key: a): string }
var b = 1; type f = { get(key: b): string, get(key: b): string }
var c = true; type f = { get(key: c): string, get(key: c): string }
var d = {}; type f = { get(key: d): string, get(key: d): string }
var e = []; type f = { get(key: e): string, get(key: e): string }
var e = [1, "a"]; type f = { get(key: e): string, get(key: e): string }
function fn() {}; type f = { get(key: fn): string, get(key: fn): string }
The following patterns are not considered problems:
type FooType = { a: number, b: string, c: number }
type FooType = { a: number, b: string, a: number }
type f = { get(key: "a"): string, get(key: "b"): string }
type f = { get(key: 1): string, get(key: 2): string }
type f = { get(key: 1.1): string, get(key: 1.2): string }
type f = { get(key: true): string, get(key: false): string }
type f = { get(key: ["a", 1]): string, get(key: ["a", 2]): string }
type f = { get(key: ["a", ["b", 1]]): string, get(key: ["a", ["b", 2]]): string }
type f = { a: number, b: string, c: number }
type f = { get(key: "a"): string, get(key: "b"): string }
type f = { get(key: "a"): string, get(key: "a", key2: "b"): string }
type f = { get(key: "a"): string, get(key: 1): string }
type f = { get(key: { a: 1 }): string, get(key: { a: 2 }): string}
var a = {}; var b = {}; type f = { get(key: a): string, get(key: b): string }
var a = 1; var b = 1; type f = { get(key: a): string, get(key: b): string }
type a = { b: <C>(config: { ...C, key: string}) => C }
export interface Foo { get foo(): boolean; get bar(): string; }
no-duplicate-type-union-intersection-members
The --fix
option on the command line automatically fixes problems reported by this rule.
Checks for duplicate members of a type union/intersection.
Options
You can disable checking intersection types using checkIntersections
.
true
(default) - check for duplicate members of intersection members.false
- do not check for duplicate members of intersection members.
{
"rules": {
"ft-flow/no-duplicate-type-union-intersection-members": [
2,
{
"checkIntersections": true
}
]
}
}
You can disable checking union types using checkUnions
.
true
(default) - check for duplicate members of union members.false
- do not check for duplicate members of union members.
{
"rules": {
"ft-flow/no-duplicate-type-union-intersection-members": [
2,
{
"checkUnions": true
}
]
}
}
The following patterns are considered problems:
type A = 1 | 2 | 3 | 1;
type B = 'foo' | 'bar' | 'foo';
type C = A | B | A | B;
type C = A & B & A & B;
The following patterns are not considered problems:
type A = 1 | 2 | 3;
type B = 'foo' | 'bar';
type C = A | B;
type C = A & B;
no-existential-type
Disallows use of the existential type (*). See more
{
"rules": {
"ft-flow/no-existential-type": 2
}
}
The following patterns are considered problems:
type T = *;
type T = U<*, *>;
const f: (*) => null = () => null;
The following patterns are not considered problems:
type T = string | null
Disallows $FlowFixMe
comment suppressions.
This is especially useful as a warning to ensure instances of $FlowFixMe
in your codebase get fixed over time.
Options
This rule takes an optional RegExp that comments a text RegExp that makes the supression valid.
{
"rules": {
"ft-flow/no-flow-fix-me-comments": [
1,
"TODO\s+[0-9]+"
]
}
}
The following patterns are considered problems:
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
const text = 'HELLO';
The following patterns are not considered problems:
const text = 'HELLO';
const text = 'HELLO';
no-flow-suppressions-in-strict-files
This rule validates that no error suppression comments (e.g. $FlowFixMe
) are used in // @flow strict
(or // @flow strict-local
) files.
This codifies the best practices as documented here:
"Do not add $FlowFixMe
to suppress the new errors as they appear; just add @flow strict
once all issues have been resolved."
Options
This rule accepts 1 option as an object to disable errors being thrown on specific suppression error types. For example, you don't want $FlowFixMe
but $FlowExpectedError
you want to allow because they are expected issues that can't be solved.
{
"rules": {
"ft-flow/no-flow-suppressions-in-strict-files": [2, {
"$FlowExpectedError": false
}]
}
}
The following patterns are considered problems:
const text: string = 42;
const text: string = 42;
const text: string = 42;
const text: string = 42;
const text: string = 42;
const text: string = 42;
const text: string = 42;
The following patterns are not considered problems:
const text: string = 42;
const text: string = 42;
const text: string = 42;
no-internal-flow-type
Warns against using internal Flow types such as React$Node
, React$Ref
and others and suggests using public alternatives instead (React.Node
, React.Ref
, …).
The following patterns are considered problems:
type X = React$AbstractComponent<Config, Instance>
type X = React$ChildrenArray<string>
type X = React$ComponentType<Props>
type X = React$Config<Prosp, DefaultProps>
type X = React$Element<typeof Component>
type X = React$ElementConfig<typeof Component>
type X = React$ElementProps<typeof Component>
type X = React$ElementRef<typeof Component>
type X = React$ElementType
type X = React$Key
type X = React$Node
type X = React$Ref<typeof Component>
type X = React$StatelessFunctionalComponent<Props>
The following patterns are not considered problems:
type X = React.AbstractComponent<Config, Instance>
type X = React.ChildrenArray<string>
type X = React.ComponentType<Props>
type X = React.Config<Props, DefaultProps>
type X = React.Element<typeof Component>
type X = React.ElementConfig<typeof Component>
type X = React.ElementProps<typeof Component>
type X = React.ElementRef<typeof Component>
type X = React.ElementType
type X = React.Key
type X = React.Node
type X = React.Ref<typeof Component>
type X = React.StatelessFunctionalComponent<Props>
type X = React$Rocks
no-mixed
Warns against "mixed" type annotations.
These types are not strict enough and could often be made more specific.
The following patterns are considered problems:
The following patterns are considered problems:
function foo(thing): mixed {}
function foo(thing): Promise<mixed> {}
function foo(thing): Promise<Promise<mixed>> {}
The following patterns are not considered problems:
function foo(thing): string {}
function foo(thing): Promise<string> {}
function foo(thing): Promise<Promise<string>> {}
(foo?: string) => {}
(foo: ?string) => {}
(foo: { a: string }) => {}
(foo: { a: ?string }) => {}
(foo: string[]) => {}
type Foo = string
type Foo = { a: string }
type Foo = { (a: string): string }
function foo(thing: string) {}
var foo: string
class Foo { props: string }
no-mutable-array
The --fix
option on the command line automatically fixes problems reported by this rule.
Requires use of $ReadOnlyArray
instead of just Array
or array shorthand notation. $ReadOnlyArray
is immutable array collection type and the superclass of Array and tuple types in Flow. Use of $ReadOnlyArray
instead of Array
can solve some "problems" in typing with Flow (e.g., 1, 2).
General reasons for using immutable data structures:
- They are simpler to construct, test, and use
- They help to avoid temporal coupling
- Their usage is side-effect free (no defensive copies)
- Identity mutability problem is avoided
- They always have failure atomicity
- They are much easier to cache
Note that initialization of a variable with an empty array is considered valid (e.g., const values: Array<string> = [];
). This behavior resembles the behavior of Flow's unsealed objects, as it is assumed that empty array is intended to be mutated.
The following patterns are considered problems:
type X = Array<string>
type X = string[]
const values: Array<Array<string>> = [];
let values: Array<Array<string>>;
The following patterns are not considered problems:
type X = $ReadOnlyArray<string>
const values: Array<$ReadOnlyArray<string>> = [];
const values: $ReadOnlyArray<string>[] = [];
const values: Array<$ReadOnlyArray<string>> = new Array();
const values: Array<$ReadOnlyArray<string>> = Array();
no-primitive-constructor-types
Disallows use of primitive constructors as types, such as Boolean
, Number
and String
. See more.
{
"rules": {
"ft-flow/no-primitive-constructor-types": 2
}
}
The following patterns are considered problems:
type x = Number
type x = String
type x = Boolean
type x = { a: Number }
type x = { a: String }
type x = { a: Boolean }
(x: Number) => {}
(x: String) => {}
(x: Boolean) => {}
The following patterns are not considered problems:
type x = number
type x = string
type x = boolean
type x = { a: number }
type x = { a: string }
type x = { a: boolean }
(x: number) => {}
(x: string) => {}
(x: boolean) => {}
type x = MyNumber
type x = MyString
type x = MyBoolean
no-types-missing-file-annotation
Disallows Flow type imports, aliases, and annotations in files missing a valid Flow file declaration (or a @noflow annotation).
{
"rules": {
"ft-flow/no-types-missing-file-annotation": 2
}
}
The following patterns are considered problems:
const x: number = 42;
type FooType = number;
import type A from "a"
import type {A} from "a"
import {type A} from "a"
export type {A} from "a"
function t<T>(): T{}
const x: number = 42;
The following patterns are not considered problems:
const x: number = 42;
type FooType = number;
type FooType = number;
import type A from "a"
import {type A} from "a"
export type {A} from "a"
export type {A} from "a"
no-unused-expressions
An extension of ESLint's no-unused-expressions
.
This rule ignores type cast expressions and optional call expressions, but otherwise behaves the same as ESLint's
no-unused-expressions
.
Bare type casts are useful, for example to assert the exhaustiveness of a switch
:
type Action
= { type: 'FOO', doFoo: (_: number) => void }
| { type: 'BAR', doBar: (_: string) => void };
type State = { foo: number, bar: string };
function runFooBar(action: Action, state: State): void {
switch (action.type) {
case 'FOO':
doFoo(state.foo);
break;
case 'BAR':
doBar(state.bar);
break;
default:
(action: empty);
console.error(`Impossible action: ${action.toString()}`);
}
}
This rule takes the same arguments as ESLint's no-unused-expressions
. See
that rule's documentation for details.
The following patterns are considered problems:
foo + 1
x?.y
The following patterns are not considered problems:
(foo: number)
x?.y()
no-weak-types
Warns against weak type annotations any, Object and Function.
These types can cause flow to silently skip over portions of your code,
which would have otherwise caused type errors.
This rule optionally takes one argument, an object to configure which type warnings to enable. By default, all of the
warnings are enabled. e.g. to disable the any
warning (allowing it to exist in your code), while continuing to warn
about Object
and Function
:
{
"rules": {
"ft-flow/no-weak-types": [2, {
"any": false,
"Object": true,
"Function": true
}]
}
}
{
"rules": {
"ft-flow/no-weak-types": [2, {
"any": false
}]
}
}
The following patterns are considered problems:
function foo(thing): any {}
function foo(thing): Promise<any> {}
function foo(thing): Promise<Promise<any>> {}
function foo(thing): Object {}
function foo(thing): Promise<Object> {}
function foo(thing): Promise<Promise<Object>> {}
function foo(thing): Function {}
function foo(thing): Promise<Function> {}
function foo(thing): Promise<Promise<Function>> {}
(foo: any) => {}
(foo: Function) => {}
(foo?: any) => {}
(foo?: Function) => {}
(foo: { a: any }) => {}
(foo: { a: Object }) => {}
(foo: any[]) => {}
type Foo = any
type Foo = Function
type Foo = { a: any }
type Foo = { a: Object }
type Foo = { (a: Object): string }
type Foo = { (a: string): Function }
function foo(thing: any) {}
function foo(thing: Object) {}
var foo: Function
var foo: Object
class Foo { props: any }
class Foo { props: Object }
var foo: any
type X = any; type Y = Function; type Z = Object
type X = any; type Y = Function; type Z = Object
const a: $FlowFixMe = 1
const a: Something = 1
The following patterns are not considered problems:
function foo(thing): string {}
function foo(thing): Promise<string> {}
function foo(thing): Promise<Promise<string>> {}
(foo?: string) => {}
(foo: ?string) => {}
(foo: { a: string }) => {}
(foo: { a: ?string }) => {}
(foo: string[]) => {}
type Foo = string
type Foo = { a: string }
type Foo = { (a: string): string }
function foo(thing: string) {}
var foo: string
class Foo { props: string }
type X = any; type Y = Object
type X = Function
function foo(thing): Function {}
const a: string = 1
const Foo = 1
object-type-curly-spacing
The --fix
option on the command line automatically fixes problems reported by this rule.
This rule enforces consistent spacing inside braces of object types.
Options
The rule has a string option:
"never"
(default): disallows spacing inside of braces."always"
: requires spacing inside of braces.
The following patterns are considered problems:
type obj = { "foo": "bar" }
type obj = {"foo": "bar" }
type obj = {"foo": "bar", ... }
type obj = {|"foo": "bar" |}
type obj = {"foo": "bar", [key: string]: string }
type obj = {
"foo": "bar", [key: string]: string }
type obj = { baz: {"foo": "qux"}, bar: 4}
type obj = {"foo": "bar"}
type obj = {"foo": "bar" }
type obj = { baz: {"foo": "qux"}, bar: 4}
type obj = { baz: { "foo": "qux" }, bar: 4}
type obj = { "foo": "bar", ...}
type obj = {|"foo": "bar" |}
type obj = {"foo": "bar", [key: string]: string }
The following patterns are not considered problems:
type obj = {baz: {"foo": "qux"}, bar: 4}
type obj = {foo: {"foo": "qux"}}
type obj = {foo: "bar"}
type obj = {foo: "bar"
}
type obj = {
foo: "bar"}
type obj = {
foo: "bar"
}
type obj = {
foo: "bar",
ee: "bar",
}
type obj = {
foo: "bar",
ee: "bar",
}
type obj = {|"foo": "bar"|}
type obj = {"foo": "bar", [key: string]: string}
type obj = { baz: { "foo": "qux" }, bar: 4 }
type obj = {}
type obj = {
foo: "bar"
}
type obj = { baz: 4 }
type obj = {| "foo": "bar" |}
type obj = { "foo": "bar", [key: string]: string }
type obj = { baz: { "foo": "qux" }, bar: 4 }
type obj = {
baz: { "foo": "qux" }, bar: 4
}
object-type-delimiter
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent separators between properties in Flow object types.
This rule takes one argument.
If it is 'comma'
then a problem is raised when using ;
as a separator.
If it is 'semicolon'
then a problem is raised when using ,
as a separator.
The default value is 'comma'
.
This rule is ported from babel/flow-object-type
, however the default option was changed.
The following patterns are considered problems:
type Foo = { a: Foo, b: Bar }
type Foo = { a: Foo; b: Bar }
type Foo = { [a: string]: Foo, [b: string]: Bar }
type Foo = { [a: string]: Foo; [b: string]: Bar }
type Foo = { (): Foo, (): Bar }
type Foo = { (): Foo; (): Bar }
declare class Foo { a: Foo, }
declare class Foo { a: Foo; }
declare class Foo { [a: string]: Foo, }
declare class Foo { a: Foo; }
declare class Foo { (): Foo, }
declare class Foo { (): Foo; }
declare class Foo { static (): Foo, }
declare class Foo { static (): Foo; }
The following patterns are not considered problems:
type Foo = { a: Foo; b: Bar }
type Foo = { a: Foo, b: Bar }
type Foo = { [a: string]: Foo; [b: string]: Bar }
type Foo = { [a: string]: Foo, [b: string]: Bar }
type Foo = { (): Foo; (): Bar }
type Foo = { (): Foo, (): Bar }
type Foo = { a: Foo, b: Bar }
type Foo = { [a: string]: Foo, [b: string]: Bar }
type Foo = { (): Foo, (): Bar }
declare class Foo { a: Foo; }
declare class Foo { a: Foo, }
declare class Foo { [a: string]: Foo; }
declare class Foo { [a: string]: Foo, }
declare class Foo { (): Foo; }
declare class Foo { (): Foo, }
type Foo = { a: Foo, b: Bar }
quotes
Enforces single quotes or double quotes around string literals.
Options
The rule has string options of:
"double"
(default) requires double quotes around string literals."single"
requires single quotes around string literals.
The following patterns are considered problems:
type T = 'hi'
type T = { test: 'hello' | 'test' }
type T = { test: "hello" | 'test', t: 'hello' }
type T = "hi"
type T = { test: "hello" | "test" }
type T = { test: "hello" | 'test', t: 'hello' }
The following patterns are not considered problems:
type T = "hi"
type T = { test: "hello" | "test" }
type T = { test: "hello" | "test", t: "hello" }
type FooType = 'hi'
type T = { test: 'hello' | 'test' }
type T = { test: 'hello' | 'test', t: 'hello' }
require-compound-type-alias
Requires to make a type alias for all union and intersection types. If these are used in "raw" forms it might be tempting to just copy & paste them around the code. However, this brings sort of a source code pollution and unnecessary changes on several parts when these compound types need to be changed.
Options
The rule has two options:
- a string option
"always"
(default)"never"
- an object
{
"rules": {
"flowtype/require-compound-type-alias": [
2,
"always",
{
"allowNull": true
}
]
}
}
allowNull
– allows compound types where one of the members is a null
, e.g. string | null
.
The following patterns are considered problems:
const foo: string | null = null;
function foo(bar: "A" | "B") {}
const foo: "A" | "B" = "A";
type Foo = { bar: "A" | "B" };
function foo(bar: { n: number } | { s: string }) {}
function foo(bar: { n: number } & { s: string }) {}
const foo: { n: number } & { s: string } = { n: 0, s: "" };
type Foo = { bar: { n: number } & { s: string } };
function foo(bar: { n: number } & { s: string }) {}
The following patterns are not considered problems:
const foo: string | null = null;
const foo: string | null = null;
type Foo = "A" | "B";
type Bar = "A" | "B"; function foo(bar: Bar) {}
type Foo = { disjoint: "A", n: number } | { disjoint: "B", s: string };
type Foo = { n: number } & { s: string };
type Bar = { n: number } & { s: string }; function foo(bar: Bar) {}
function foo(bar: "A" | "B") {}
function foo(bar: { n: number } & { s: string }) {}
require-exact-type
The --fix
option on the command line automatically fixes problems reported by this rule.
This rule enforces exact object types.
Options
The rule has one string option:
"always"
(default): Report all object type definitions that aren't exact."never"
: Report all object type definitions that are exact.
{
"rules": {
"ft-flow/require-exact-type": [
2,
"always"
]
}
}
{
"rules": {
"ft-flow/require-exact-type": [
2,
"never"
]
}
}
The following patterns are considered problems:
type foo = {};
type foo = { bar: string };
type foo = Array<{bar: string}>;
(foo: Array<{bar: string}>) => {};
interface StackFrame {
colno?: number;
lineno?: number;
filename?: string;
function?: { name: string };
}
type foo = {| |};
type foo = {| bar: string |};
type foo = { bar: {| baz: string |} };
type foo = Array<{| bar: string |}>;
(foo: Array<{| bar: string |}>) => {};
interface StackFrame {
colno?: number;
lineno?: number;
filename?: string;
function?: {| name: string |};
}
The following patterns are not considered problems:
type foo = {| |};
type foo = {| bar: string |};
type foo = { [key: string]: string };
type foo = number;
type foo = {| |};
type foo = {| bar: string |};
type foo = {| bar: {| baz: string |} |};
type foo = Array<{| bar: string |}>;
type foo = number;
interface StackFrame {
colno?: number;
lineno?: number;
filename?: string;
function?: {| name: string |};
}
declare class MyEvent extends Event {
key: string
}
type foo = { };
type foo = { bar: string };
type foo = { bar: { baz: string } };
type foo = Array<{bar: string}>;
type foo = number;
interface StackFrame {
colno?: number;
lineno?: number;
filename?: string;
function?: {| name: string |};
}
type A = { a: string, ... }
require-indexer-name
The --fix
option on the command line automatically fixes problems reported by this rule.
This rule validates Flow object indexer name.
Options
The rule has a string option:
"never"
(default): Never report files that are missing an indexer key name."always"
: Always report files that are missing an indexer key name.
{
"rules": {
"ft-flow/require-indexer-name": [
2,
"always"
]
}
}
The following patterns are considered problems:
type foo = { [string]: number };
The following patterns are not considered problems:
type foo = { [key: string]: number };
type foo = { [key: string]: number };
type foo = { [string]: number };
require-inexact-type
This rule enforces explicit inexact object types.
Options
The rule has one string option:
"always"
(default): Report all object type definitions that aren't explicit inexact, but ignore exact objects."never"
: Report all object type definitions that are explicit inexact.
{
"rules": {
"ft-flow/require-inexact-type": [
2,
"always"
]
}
}
{
"rules": {
"ft-flow/require-inexact-type": [
2,
"never"
]
}
}
The following patterns are considered problems:
type foo = {};
type foo = { bar: string };
type foo = {};
type foo = { bar: string };
type foo = {...};
type foo = { bar: string, ... };
The following patterns are not considered problems:
type foo = { foo: string, ... };
interface Foo { foo: string }
declare class Foo { foo: string }
type foo = {| |};
type foo = {| bar: string |};
type foo = { [key: string]: string, ... };
type foo = number;
type foo = {| |};
type foo = {...};
type foo = { bar: string, ... };
type foo = {| bar: string |};
type foo = number;
type foo = { };
type foo = {| |};
type foo = { bar: string };
type foo = {| bar: string |};
type foo = number;
require-parameter-type
Requires that all function parameters have type annotations.
Options
You can skip all arrow functions by providing the excludeArrowFunctions
option with true
.
Alternatively, you can want to exclude only concise arrow functions (e.g. x => x * 2
). Provide excludeArrowFunctions
with expressionsOnly
for this.
{
"rules": {
"ft-flow/require-parameter-type": [
2,
{
"excludeArrowFunctions": true
}
]
}
}
{
"rules": {
"ft-flow/require-parameter-type": [
2,
{
"excludeArrowFunctions": "expressionsOnly"
}
]
}
}
You can exclude parameters that match a certain regex by using excludeParameterMatch
.
{
"rules": {
"flowtype/require-parameter-type": [
2,
{
"excludeParameterMatch": "^_"
}
]
}
}
This excludes all parameters that start with an underscore (_
).
The default pattern is a^
, which doesn't match anything, i.e., all parameters are checked.
The following patterns are considered problems:
(foo) => {}
function x(foo) {}
function x(foo) {}
(foo = 'FOO') => {}
(...foo) => {}
({foo}) => {}
([foo]) => {}
({foo = 1} = {}) => {}
(foo) => {}
(foo) => {}
function x(foo) {}
(_foo: number, bar) => {}
(_foo, bar) => {}
The following patterns are not considered problems:
(foo: string) => {}
(foo: string = 'FOO') => {}
(...foo: string) => {}
const f: Foo = (a, b) => 42;
({foo}: {foo: string}) => {}
([foo]: Array) => {}
type fn = (a: string, b: number) => number;
const f: fn = (a, b) => {}
(foo) => {}
(foo) => {}
(foo) => 3
(_foo, bar: string) => {}
(_foo: number, bar: string) => {}
(foo) => {}
require-readonly-react-props
This rule validates that React props are marked as $ReadOnly
. React props are immutable and modifying them could lead to unexpected results. Marking prop shapes as $ReadOnly
avoids these issues.
The rule tries its best to work with both class and functional components. For class components, it does a fuzzy check for one of "Component", "PureComponent", "React.Component" and "React.PureComponent". It doesn't actually infer that those identifiers resolve to a proper React.Component
object.
For example, this will NOT be checked:
import MyReact from 'react';
class Foo extends MyReact.Component { }
As a result, you can safely use other classes without getting warnings from this rule:
class MyClass extends MySuperClass { }
React's functional components are hard to detect statically. The way it's done here is by searching for JSX within a function. When present, a function is considered a React component:
type Props = { };
function MyComponent(props: Props) {
return <p />;
}
type Options = { };
function SomeHelper(options: Options) {
}
function helper() { return <p /> }
function MyComponent(props: Props) {
return helper();
}
The rule only works for locally defined props that are marked with a $ReadOnly
or using covariant notation. It doesn't work with imported props:
import { type ImportedProps } from './somewhere';
class Foo extends React.Component<ImportedProps> { }
type Props = {|
+foo: string
|};
class Bar extends React.Component<Props> { }
type Props = {|
+foo: string,
bar: number,
|};
class Bar extends React.Component<Props> { }
type Props = {|
+foo: string,
...bar,
|};
class Bar extends React.Component<Props> { }
{
"rules": {
"ft-flow/require-readonly-react-props": 2
}
}
Optionally, you can enable support for implicit exact Flow types (useful when using exact_by_default=true
Flow option):
{
"rules": {
"ft-flow/require-readonly-react-props": [
2,
{
"useImplicitExactTypes": true
}
]
}
}
If you’re using experimental TypeScript syntax via the experimental.ts_syntax=true
Flow option, you can adjust this lint rule to check for that syntax, e.g., Readonly
versus $ReadOnly
.
{
"rules": {
"ft-flow/require-readonly-react-props": [
2,
{
"useExperimentalTypeScriptSyntax": true
}
]
}
}
The following patterns are considered problems:
type Props = { }; class Foo extends React.Component<Props> { }
type Props = { }; class Foo extends React.Component<Props> { }
type Props = Readonly<{ }>; class Foo extends React.Component<Props> { }
type Props = Readonly<{ }>; class Foo extends React.Component<Props> { }
type OtherProps = { foo: string }; class Foo extends React.Component<OtherProps> { }
class Foo extends React.Component<{}> { }
type Props = { bar: {} }; class Foo extends React.Component<Props, State> { }
type Props = { }; class Foo extends Component<Props> { }
type Props = { }; class Foo extends PureComponent<Props> { }
export type Props = {}; class Foo extends Component<Props> { }
type Props = {| foo: string |}; class Foo extends Component<Props> { }
type Props = {| foo: string |} | {| bar: number |}; class Foo extends Component<Props> { }
type Props = { foo: string } | { bar: number }; class Foo extends Component<Props> { }
type Props = {| +foo: string, ...bar |}; class Foo extends Component<Props> { }
type Props = {| +foo: string, -bar: number |}; class Foo extends Component<Props> { }
type Props = { }; function Foo(props: Props) { return <p /> }
type Props = { }; function Foo(props: Props) { return <p /> }
type Props = Readonly<{ }>; function Foo(props: Props) { return <p /> }
type Props = Readonly<{ }>; function Foo(props: Props) { return <p /> }
type Props = { }; function Foo(props: Props) { return foo ? <p /> : <span /> }
function Foo(props: {}) { return <p /> }
export type Props = {}; function Foo(props: Props) { return <p /> }
The following patterns are not considered problems:
class Foo extends React.Component<$ReadOnly<{}>> { }
class Foo extends React.Component<Readonly<{}>> { }
type Props = $ReadOnly<{}>; class Foo extends React.Component<Props> { }
type Props = $ReadOnly<{}>; class Foo extends React.PureComponent<Props> { }
class Foo extends React.Component<$ReadOnly<{}, State>> { }
type Props = $ReadOnly<{}>; class Foo extends React.Component<Props, State> { }
type Props = $ReadOnly<{}>; class Foo extends Component<Props> { }
type Props = $ReadOnly<{}>; class Foo extends PureComponent<Props> { }
type FooType = {}; class Foo extends Bar<FooType> { }
class Foo { }
export type Props = $ReadOnly<{}>; class Foo extends Component<Props, State> { }
export type Props = $ReadOnly<{}>; export class Foo extends Component<Props> { }
type Props = {| +foo: string |}; class Foo extends Component<Props> { }
type Props = {| +foo: string, +bar: number |}; class Foo extends Component<Props> { }
type Props = {| +foo: string |} | {| +bar: number |}; class Foo extends Component<Props> { }
type Props = { +foo: string } | { +bar: number }; class Foo extends Component<Props> { }
type Props = $FlowFixMe; class Foo extends Component<Props> { }
type Props = {||}; class Foo extends Component<Props> { }
type Props = {||}; class Foo extends Component<Props> { }
type Props = {}; class Foo extends Component<Props> { }
class Foo extends Component<{||}> { }
class Foo extends Component<{||}> { }
class Foo extends Component<{}> { }
class Foo extends React.Component<UnknownProps> { }
import { type Props } from "file"; class Foo extends React.Component<Props> { }
type Props = {}; function Foo() { }
type Props = $ReadOnly<{}>; function Foo(props: Props) { }
type Props = Readonly<{}>; function Foo(props: Props) { }
type Props = {}; function Foo(props: OtherProps) { }
function Foo() { return <p /> }
function Foo(props: $FlowFixMe) { return <p /> }
function Foo(props: {||}) { return <p /> }
function Foo(props: {||}) { return <p /> }
function Foo(props: {}) { return <p /> }
require-return-type
Requires that functions have return type annotation.
Options
You can skip all arrow functions by providing the excludeArrowFunctions
option with true
.
Alternatively, you can exclude a concise arrow function (e.g. () => 2
). Provide excludeArrowFunctions
with expressionsOnly
for this.
{
"rules": {
"ft-flow/require-return-type": [
2,
"always",
{
"excludeArrowFunctions": true
}
]
}
}
{
"rules": {
"ft-flow/require-return-type": [
2,
"always",
{
"excludeArrowFunctions": "expressionsOnly"
}
]
}
}
You can exclude or include specific tests with the includeOnlyMatching
and excludeMatching
rules.
{
"rules": {
"ft-flow/require-return-type": [
2,
"always",
{
"includeOnlyMatching": [
"^F.*",
"Ba(r|z)"
]
}
]
}
}
{
"rules": {
"ft-flow/require-return-type": [
2,
"always",
{
"excludeMatching": [
"^F.*",
"Ba(r|z)"
]
}
]
}
}
Both rules take an array that can contain either strings or valid RegExp statements.
The following patterns are considered problems:
(foo) => { return "foo"; }
(foo) => { return "foo"; }
(foo) => "foo"
(foo) => ({})
(foo) => { return 1; }
(foo): undefined => { return; }
(foo): void => { return; }
(foo): undefined => { return undefined; }
(foo): void => { return void 0; }
(foo): undefined => { return; }
(foo): void => { return; }
(foo) => { return; }
(foo): undefined => { return undefined; }
(foo) => { return undefined; }
(foo) => { return void 0; }
(foo) => { return 1; }
(foo) => { return undefined; }
async () => { return 2; }
async () => {}
async function x() {}
async (): Promise<void> => { return; }
async (): Promise<undefined> => { return; }
class Test { constructor() { } }
class Test { foo() { return 42; } }
class Test { foo = () => { return 42; } }
class Test { foo = () => 42; }
function* x() {}
() => { return 3; }
async () => { return 4; }
function foo() { return 42; }
function bar() { return 42; }
const foo = () => { return 42; };
const bar = () => { return 42; }
const foo = { bar() { return 42; }, foobar: function() { return 42; } }
const foo = { bar() { return 42; }, baz() { return 42; } }
function * foo() { yield 2; }
async function * foo() { yield 2; }
The following patterns are not considered problems:
return;
(foo): string => {}
const f: Foo = (a, b) => 42;
(foo): string => {}
type fn = (a: string, b: number) => number;
const f: fn = (a, b) => { return 42; }
(foo) => { return; }
(foo): Object => ( {} )
(foo) => { return undefined; }
(foo) => { return void 0; }
(foo): undefined => { return; }
(foo): void => { return; }
(foo) => { return; }
(foo) => { return undefined; }
(foo) => { return void 0; }
(foo): undefined => { return undefined; }
(foo): void => { return void 0; }
(foo) => { return 1; }
(foo) => { return 1; }
(foo) => { return undefined; }
async function doThing(): Promise<void> {}
async function doThing(): Promise<void> {}
async function doThing() {}
function* doThing(): Generator<number, void, void> { yield 2; }
class Test { constructor() { } }
class Test { constructor() { } }
class Test { foo() { return 42; } }
class Test { foo = () => { return 42; } }
class Test { foo = () => 42; }
class Test { foo = (): number => { return 42; } }
class Test { foo = (): number => 42; }
async (foo): Promise<number> => { return 3; }
() => 3
() => { return 4; }
() => undefined
() => undefined
() => { return undefined; }
() => 3
async () => 3
function foo() { return 42; }
function foo() { return 42; }
function foo(): number { return 42; }
function bar() { return 42; }
function foo(): number { return 42; }
function bar() { return 42; }
function foo(): number { return 42; }
function bar() { return 42; }
function foo(): number { return 42; }
function bar() { return 42; }
const foo = { baz() { return 42; } }
const foo = { bar() { return 42; } }
function * foo(): Iterable<number> { yield 2; }
async function * foo(): AsyncIterable<number> { yield 2; }
require-types-at-top
Requires all type declarations to be at the top of the file, after any import declarations.
Options
The rule has a string option:
The default value is "always"
.
The following patterns are considered problems:
const foo = 3;
type Foo = number;
const foo = 3;
opaque type Foo = number;
const foo = 3;
export type Foo = number;
const foo = 3;
export opaque type Foo = number;
const foo = 3;
type Foo = number | string;
import bar from "./bar";
const foo = 3;
type Foo = number;
The following patterns are not considered problems:
type Foo = number;
const foo = 3;
opaque type Foo = number;
const foo = 3;
export type Foo = number;
const foo = 3;
export opaque type Foo = number;
const foo = 3;
type Foo = number;
const foo = 3;
import bar from "./bar";
type Foo = number;
type Foo = number;
import bar from "./bar";
const foo = 3;
type Foo = number;
require-valid-file-annotation
This rule validates Flow file annotations.
This rule can optionally report missing or missed placed annotations, common typos (e.g. // @floww
), and enforce a consistent annotation style.
Options
The rule has a string option:
"never"
(default): Never report files that are missing an @flow
annotation."always"
: Always report files that are missing an @flow
annotation
This rule has an object option:
{
"rules": {
"ft-flow/require-valid-file-annotation": [
2,
"always"
]
}
}
{
"rules": {
"ft-flow/require-valid-file-annotation": [
2,
"always", {
"annotationStyle": "block",
"strict": true,
}
]
}
}
The following patterns are considered problems:
#!/usr/bin/env node
#!/usr/bin/env node
a;
;
;
a;
a;
a;
a;
a;
b;
a;
b;
a;
b;
The following patterns are not considered problems:
a;
a;
a;
a;
a;
a;
a;
a;
require-variable-type
Requires that all variable declarators have type annotations.
Options
You can exclude variables that match a certain regex by using excludeVariableMatch
.
This excludes all parameters that start with an underscore (_
).
The default pattern is a^
, which doesn't match anything, i.e., all parameters are checked.
{
"rules": {
"ft-flow/require-variable-type": [
2,
{
"excludeVariableMatch": "^_"
}
]
}
}
You can choose specific variable types (var
, let
, and const
) to ignore using excludeVariableTypes
.
This excludes var
and let
declarations from needing type annotations, but forces const
declarations to have it.
By default, all declarations are checked.
{
"rules": {
"ft-flow/require-variable-type": [
2,
{
"excludeVariableTypes": {
"var": true,
"let": true,
"const": false,
}
}
]
}
}
The following patterns are considered problems:
var foo = "bar"
var foo : string = "bar", bar = 1
var _foo = "bar", bar = 1
var foo = "bar", bar = 1; const oob : string = "oob"; let hey = "yah"
The following patterns are not considered problems:
var foo : string = "bar"
var foo : string = "bar", bar : number = 1
var _foo = "bar", bar : number = 1
var foo = "bar", bar = 1
var foo = "bar", bar = 1; const oob : string = "oob"; let hey = "yah"
semi
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent use of semicolons after type aliases.
This rule takes one argument. If it is 'never'
then a problem is raised when there is a semicolon after a type alias. If it is 'always'
then a problem is raised when there is no semicolon after a type alias.
The default value is 'always'
.
The following patterns are considered problems:
class Foo { foo: string }
class Foo { foo: string; }
type FooType = {}
type FooType = {}
type FooType = {};
opaque type FooType = {}
The following patterns are not considered problems:
type FooType = {};
type FooType = {};
(foo: string) => {}
class Foo { foo: string; }
class Foo { foo: string }
type FooType = { a: number;
b: string;
};
type FooType = { a: number;
b: string;
}
type FooType = {}
type FooType = {}
opaque type FooType = {};
sort-keys
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces natural, case-insensitive sorting of Object annotations.
Options
The first option specifies sort order.
"asc"
(default) - enforce ascending sort order."desc"
- enforce descending sort order.
{
"rules": {
"ft-flow/sort-keys": [
2,
"asc"
]
}
}
The following patterns are considered problems:
type FooType = { a: number, c: number, b: string }
type FooType = { a: number, b: number }
type FooType = { b: number, C: number, a: string }
type FooType = { a: number, c: number, C: number, b: string }
type FooType = { a: number, C: number, c: number, b: string }
type FooType = { 1: number, 10: number, 2: boolean }
type FooType = { a: number, c: number, b: string }
type FooType = {
a: number,
c: number,
b: string,
}
type FooType = {
a: $ReadOnlyArray<number>,
c: $ReadOnlyMap<string, number>,
b: Map<string, Array<Map<string, number>>>,
}
type FooType = {
...ErrorsInRecursiveGenericTypeArgsButDoesNotFix<{
y: boolean,
x: string,
z: {
j: string,
l: number,
k: boolean,
},
}>,
a: number,
c: string,
b: Map<string, Array<ErrorsInRecursiveGenericTypeArgsButDoesNotFix<{
y: boolean,
x: string,
z: {
j: string,
l: number,
k: boolean,
},
}>>>,
}
type FooType = {
...BPreservesSpreadOrder,
...APreservesSpreadOrder,
c: string,
b: number,
}
type FooType = {
...BPreservesSpreadSpans,
...APreservesSpreadSpans,
c: string,
b: number,
...CPreservesSpreadSpans,
e: string,
d: number,
}
type FooType = {
...BPreservesSpreadOrderAndTypeArgs<string, number>,
...APreservesSpreadOrderAndTypeArgs<number>,
c: string,
b: number,
}
type FooType = {
... BType<Generic> ,
... AType ,
c:string,
b: number,
dWithoutComma: boolean
}
type FooType = {
+a: number,
c: number,
b: string,
}
type FooType = {
-a: number,
c: number,
b: string,
}
type FooType = {
a?: number,
c: ?number,
b: string,
}
type FooType = {
a: (number) => void,
c: number,
b: (param: string) => number,
}
type FooType = {
a: number | string | boolean,
c: number,
b: (param: string) => number,
}
type FooType = {
c: number,
a: number | string | boolean,
b: (param: string) => number,
}
type FooType = {
c: {
z: number,
x: string,
y: boolean,
},
a: number | string | boolean,
b: (param: string) => number,
}
type FooType = {
c: {
z: {
j: string,
l: number,
k: boolean,
},
x: string,
y: boolean,
},
a: number | string | boolean,
b: (param: string) => number,
}
type FooType = {
+c: number,
-b: number,
a: number,
}
type FooType = {|
+c: number,
-b: number,
a: number,
|}
type FooType = {
a(number): void,
c: number,
b(param: string): number,
}
type FooType = {
a: number | string | boolean,
c: number,
b(param: string): number,
}
type FooType = {
c: number,
a: number | string | boolean,
b(param: string): number,
}
type FooType = {
c: {
z: number,
x: string,
y: boolean,
},
a: number | string | boolean,
b(param: string): number,
}
type FooType = {
c: {
z: {
j: string,
l: number,
k: boolean,
},
x: string,
y: boolean,
},
a: number | string | boolean,
b(param: string): number,
}
type FooType = {
a: number | string | boolean,
c: number,
b(param: string): number,
}
export type GroupOrdersResponseType = {|
isSuccess: boolean,
code: number,
message?: string,
errorMessage: string,
result: {|
OrderNumber: string,
Orders: GroupOrderSummaryType[],
PlacedOn: string,
Status: string,
ReturnText: string,
IncludesLegacyOrder: boolean
|}
|};
The following patterns are not considered problems:
type FooType = { a: number }
type FooType = { a: number, b: number, c: (boolean | number) }
type FooType = { a: string, b: foo, C: number }
type FooType = { 1: number, 2: boolean, 10: number }
type FooType = { c: number, b: number, a: number }
type FooType = { C: number, b: string, a: {} }
type FooType = { 10: number, 2: number, 1: boolean }
type FooType = { b: number, a: number }
type FooType = { a: string, b(): number, c: boolean }
type FooType = { a(): string, b: number, c: boolean }
sort-type-union-intersection-members
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces that members of a type union/intersection are sorted alphabetically.
Options
You can specify the sort order using order
.
"asc"
(default) - enforce ascending sort order."desc"
- enforce descending sort order.
{
"rules": {
"ft-flow/sort-type-union-intersection-members": [
2,
{
"order": "asc"
}
]
}
}
You can disable checking intersection types using checkIntersections
.
true
(default) - enforce sort order of intersection members.false
- do not enforce sort order of intersection members.
{
"rules": {
"ft-flow/sort-type-union-intersection-members": [
2,
{
"checkIntersections": true
}
]
}
}
You can disable checking union types using checkUnions
.
true
(default) - enforce sort order of union members.false
- do not enforce sort order of union members.
{
"rules": {
"ft-flow/sort-type-union-intersection-members": [
2,
{
"checkUnions": true
}
]
}
}
You can specify the ordering of groups using groupOrder
.
Each member of the type is placed into a group, and then the rule sorts alphabetically within each group.
The ordering of groups is determined by this option.
keyword
- Keyword types (any
, string
, etc)named
- Named types (A
, A['prop']
, B[]
, Array<C>
)literal
- Literal types (1
, 'b'
, true
, etc)function
- Function types (() => void
)object
- Object types ({ a: string }
, { [key: string]: number }
)tuple
- Tuple types ([A, B, C]
)intersection
- Intersection types (A & B
)union
- Union types (A | B
)nullish
- null
and undefined
{
"rules": {
"ft-flow/sort-type-union-intersection-members": [
2,
{
"groupOrder": [
'keyword',
'named',
'literal',
'function',
'object',
'tuple',
'intersection',
'union',
'nullish',
]
}
]
}
}
The following patterns are considered problems:
type T1 = B | A;
type T2 = { b: string } & { a: string };
type T3 = [1, 2, 4] & [1, 2, 3];
type T4 =
| [1, 2, 4]
| [1, 2, 3]
| { b: string }
| { a: string }
| (() => void)
| (() => string)
| 'b'
| 'a'
| 'b'
| 'a'
| string[]
| number[]
| B
| A
| string
| any;
The following patterns are not considered problems:
type T1 = A | B;
type T2 = { a: string } & { b: string };
type T3 = [1, 2, 3] & [1, 2, 4];
type T4 =
| any
| string
| A
| B
| number[]
| string[]
| 'a'
| 'a'
| 'b'
| 'b'
| (() => string)
| (() => void)
| { a: string }
| { b: string }
| [1, 2, 3]
| [1, 2, 4];
space-after-type-colon
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent spacing after the type annotation colon.
Options
This rule has a string argument.
"always"
(default): Require a space after the type annotation colon (e.g. foo: BarType)."never"
: Require no spaces after the type annotation colon (e.g. foo:BarType).
This rule has an option object.
"allowLineBreak"
- Allow a line break to count as a space following the annotation colon.
"true"
: Enable"false"
: Disable
{
"rules": {
"ft-flow/space-after-type-colon": [
2,
"always", {
"allowLineBreak": false
}
]
}
}
The following patterns are considered problems:
(foo: string) => {}
(foo: string) => {}
(foo:(() => void)) => {}
(foo: (() => void)) => {}
(foo: (() => void)) => {}
({ lorem, ipsum, dolor } : SomeType) => {}
(foo:{ a: string, b: number }) => {}
({ a, b } :{ a: string, b: number }) => {}
([ a, b ] :string[]) => {}
(i?:number) => {}
(i?: number) => {}
(i?: number) => {}
(foo:
{ a: string, b: number }) => {}
(foo:
{ a: string, b: number }) => {}
(foo:
{ a: string, b: number }) => {}
():Object => {}
(): Object => {}
(): Object => {}
():(() => void) => {}
(): (() => void) => {}
(): (() => void) => {}
export default function (foo: string) {}
function foo (foo: string) {}
(foo:string) => {}
function foo (foo:string) {}
async function foo({ lorem, ipsum, dolor }:SomeType) {}
function x(i?:number) {}
function x(i?: number) {}
function x(i?: number) {}
function a():x {}
function a(): x {}
function a(): x {}
type X = (foo:number) => string
type X = (foo: number) => string
type X = (foo: number) => string
type X = (foo:?number) => string
type X = (foo:(number)) => string
type X = (foo:((number))) => string
type X = (foo: ((number))) => string
type X = (foo: ((number))) => string
type X = (foo:?(number)) => string
type TArrayPredicate = (el: T, i?:number) => boolean
type TArrayPredicate = (el: T, i?: number) => boolean
type TArrayPredicate = (el:T, i?: number) => boolean
class X { foo:string }
class X { foo: string }
class X { foo:?string }
class X { foo: ?string }
class X { static foo:number }
class X { static foo: number }
class X { static foo :number }
class X { static foo : number }
declare class X { static foo:number }
declare class X { static foo: number }
declare class X { static foo :number }
declare class X { static foo : number }
class X { +foo:string }
class X { +foo: string }
class X { +foo: string }
class X { static +foo:string }
class X { static +foo: string }
class X { static +foo: string }
type X = { foo:string }
type X = { foo:string }
type X = { foo: string }
type X = { foo: string }
type X = { foo?:string }
type X = { foo?: string }
type X = { foo?:?string }
type X = { foo?: ?string }
type Foo = { barType:(string | () => void) }
type Foo = { barType:(((string | () => void))) }
type Foo = { barType: (string | () => void) }
type Foo = { barType: (string | () => void) }
type Foo = { barType: ((string | () => void)) }
type X = { get:() => A; }
type X = { get:<X>() => A; }
type X = { get: () => A; }
type X = { get: <X>() => A; }
type X = { get: () => A; }
type X = { get: <X>() => A; }
type X = { +foo:string }
type X = { +foo: string }
type X = { +foo: string }
type X = { +foo?:string }
type X = { +foo?: string }
type X = { +foo?: string }
type X = { [a:b]: c }
type X = { [a: b]:c }
type X = { [a: b]: c }
type X = { +[a:b]: c }
type X = { +[a: b]:c }
type X = { +[a: b]: c }
type X = { [a: b]:c }
type X = { [a:b]: c }
type X = { [a: b]: c }
type X = { [a:b]:c }
type X = { [a: b]: c }
type X = { [a: b]: c }
type X = { [a:(b)]:(c) }
type X = { [a: (b)]: (c) }
const x = ({}: {})
const x = ({}:{})
const x = ({}: {})
((x): (string))
((x):(string))
((x): (string))
const x:number = 7;
let x:number = 42;
var x:number = 42;
The following patterns are not considered problems:
(foo) => {}
(foo: string) => {}
(foo: (string|number)) => {}
(foo:string) => {}
(foo: string) => {}
(foo:(() => void)) => {}
(foo: (() => void)) => {}
({ lorem, ipsum, dolor }: SomeType) => {}
(foo: { a: string, b: number }) => {}
({ a, b }: ?{ a: string, b: number }) => {}
([ a, b ]: string[]) => {}
(i?: number) => {}
(i?:number) => {}
(foo:
{ a: string, b: number }) => {}
(foo:
{ a: string, b: number }) => {}
():Object => {}
(): Object => {}
():(number | string) => {}
(): (number | string) => {}
():number|string => {}
(): number|string => {}
():(() => void) => {}
(): (() => void) => {}
():( () => void ) => {}
(): ( () => void ) => {}
(): { a: number, b: string } => {}
() :{ a:number, b:string } => {}
function x(foo: string) {}
class Foo { constructor(foo: string) {} }
function x(foo:string) {}
class Foo { constructor(foo:string) {} }
async function foo({ lorem, ipsum, dolor }: SomeType) {}
function x({ a, b }: { a: string, b: number }) {}
function x(i?: number) {}
function x(i?:number) {}
function a(): x {}
function a():x {}
function a(): (number | string) {}
function a() :(number | string) {}
type X = (foo: number) => string;
type X = (foo : number) => string;
type X = (foo: ?number) => string;
type X = (foo? : ?number) => string;
type X = (foo: ?{ x: number }) => string;
type X = (foo:number) => string;
type X = (foo:?{ x:number }) => string;
type X = (foo: (number)) => string
type X = (foo: ((number))) => string
type X = (foo:((number))) => string
type X = ?(foo: ((number))) => string
type X = ?(foo:((number))) => string
type TArrayPredicate = (el: T, i?: number) => boolean
type TArrayPredicate = (el:T, i?:number) => boolean
type X = (number) => string;
type X = (?number) => string;
type X = number => string;
type X = ?number => string;
type X = ({ foo: bar }) => string;
type X = (number) => string;
type X = (?number) => string;
type X = number => string;
type X = ?number => string;
type X = ({ foo: bar }) => string;
class Foo { bar }
class Foo { bar = 3 }
class Foo { bar: string }
class Foo { bar: ?string }
class Foo { bar:string }
class Foo { bar:?string }
class X { static foo : number }
class X { static foo :number }
declare class X { static foo : number }
declare class X { static foo :number }
class X { +foo: string }
class X { static +foo: string }
class X { +foo:string }
class X { static +foo:string }
type X = { foo: string }
type X = { foo:string }
type X = { foo?: string }
type X = { foo?: ?string }
type X = { foo?:?string }
type Foo = { barType: (string | () => void) }
type Foo = { barType: ((string | () => void)) }
type Foo = { barType:(string | () => void) }
type Foo = { barType:((string | () => void)) }
type X = { get(): A; }
type X = { get<X>(): A; }
type X = { get(): A; }
type X = { get<X>(): A; }
type X = { get: () => A; }
type X = { get: <X>() => A; }
type X = { get:() => A; }
type X = { get:<X>() => A; }
type X = { +foo: string }
type X = { +foo?: string }
type X = { +foo:string }
type X = { +foo?:string }
type X = { [a: b]: c }
type X = { [a:b]:c }
type X = { +[a: b]: c }
type X = { +[a:b]:c }
type X = { [string]: c }
type X = { [string]:c }
const x = ({}:{})
const x = ({}: {})
((x):(string))
((x): (string))
const x: number = 7;
let x: number = 42;
var x: number = 42;
space-before-generic-bracket
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent spacing before the opening <
of generic type annotation parameters.
This rule takes one argument. If it is 'never'
then a problem is raised when there is a space before the <
. If it is 'always'
then a problem is raised when there is no space before the <
.
The default value is 'never'
.
The following patterns are considered problems:
type X = Promise <string>
type X = Promise <string>
type X = Promise <string>
type X = Promise<string>
type X = Promise <string>
The following patterns are not considered problems:
type X = Promise<string>
type X = Promise <string>
space-before-type-colon
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent spacing before the type annotation colon.
This rule takes one argument. If it is 'always'
then a problem is raised when there is no space before the type annotation colon. If it is 'never'
then a problem is raised when there is a space before the type annotation colon. The default value is 'never'
.
The following patterns are considered problems:
(foo : string) => {}
(foo ? : string) => {}
(foo: string) => {}
(foo : string) => {}
(foo?: string) => {}
(foo ? : string) => {}
(foo ?: string) => {}
({ lorem, ipsum, dolor } : SomeType) => {}
(foo : { a: string, b: number }) => {}
({ a, b } : { a: string, b: number }) => {}
([ a, b ] : string[]) => {}
() : x => {}
(): x => {}
() : x => {}
function x(foo : string) {}
function x(foo: string) {}
var x = function (foo : string) {}
var x = function (foo: string) {}
class Foo { constructor(foo : string ) {} }
class Foo { constructor(foo: string ) {} }
async function foo({ lorem, ipsum, dolor } : SomeType) {}
function a() : x {}
function a(): x {}
function a() : x {}
type X = (foo :string) => string;
type X = (foo:string) => string;
type X = (foo :string) => string;
type X = (foo? :string) => string;
type X = (foo? :string) => string;
type X = (foo?:string) => string;
type X = (foo? :?string) => string;
class X { foo :string }
class X { foo: string }
class X { foo :?string }
class X { foo: ?string }
class X { static foo : number }
class X { static foo :number }
class X { static foo: number }
class X { static foo:number }
declare class Foo { static bar :number; }
declare class Foo { static bar : number; }
declare class Foo { static bar:number; }
declare class Foo { static bar: number; }
class X { +foo: string }
class X { +foo : string }
class X { +foo : string }
class X { static +foo: string }
class X { static +foo : string }
class X { static +foo : string }
type X = { foo : string }
type X = { foo : string }
type X = { foo: string }
type X = { foo : string }
type X = { foo? : string }
type X = { foo?: string }
type X = { foo? : string }
type X = { foo ?: string }
type X = { +foo: string }
type X = { +foo : string }
type X = { +foo : string }
type X = { +foo?: string }
type X = { +foo? : string }
type X = { +foo? : string }
type X = { [a: b] : c }
type X = { [a : b]: c }
type X = { [a : b] : c }
type X = { +[a:b] : c }
type X = { +[a : b]: c }
type X = { +[a : b] : c }
type X = { [a : b]: c }
type X = { [a: b] : c }
type X = { [a : b] : c }
type X = { [a:b]:c }
type X = { [a : b] : c }
type X = { [a : b] : c }
type X = { [a:(b)]:(c) }
type X = { [a : (b)] : (c) }
const x = ({} :{})
const x = ({}:{})
const x = ({} :{})
((x) : string)
((x): string)
((x) : string)
const x:number = 7;
let x:number = 42;
var x:number = 42;
The following patterns are not considered problems:
(foo) => {}
(foo: string) => {}
(foo?: string) => {}
(foo ?: string) => {}
(foo: string) => {}
(foo : string) => {}
(foo? : string) => {}
(foo ? : string) => {}
(foo ? : string) => {}
({ lorem, ipsum, dolor }: SomeType) => {}
(foo: { a: string, b: number }) => {}
({ a, b }: ?{ a: string, b: number }) => {}
(): { a: number, b: string } => {}
() : { a : number, b : string } => {}
([ a, b ]: string[]) => {}
(): x => {}
() : x => {}
(): (number | string) => {}
() : (number | string) => {}
function x(foo: string) {}
function x(foo : string) {}
var x = function (foo: string) {}
var x = function (foo : string) {}
class X { foo({ bar }: Props = this.props) {} }
class Foo { constructor(foo: string ) {} }
class Foo { constructor(foo : string ) {} }
async function foo({ lorem, ipsum, dolor }: SomeType) {}
function x({ a, b }: { a: string, b: number }) {}
function a(): x {}
function a() : x {}
function a(): (number | string) {}
function a() : (number | string) {}
type X = (foo:string) => number;
type X = (foo: string) => number;
type X = (foo: ?string) => number;
type X = (foo?: string) => number;
type X = (foo?: ?string) => number;
type X = (foo ?: string) => number;
type X = (foo? : string) => number
type X = (foo? : ?string) => number
type X = (number) => string;
type X = (?number) => string;
type X = number => string;
type X = ?number => string;
type X = ({ foo: bar }) => string;
type X = (number) => string;
type X = (?number) => string;
type X = number => string;
type X = ?number => string;
type X = ({ foo : bar }) => string;
class Foo { bar }
class Foo { bar = 3 }
class Foo { bar: string }
class Foo { bar: ?string }
class Foo { bar:?string }
class Foo { bar : string }
class X { static foo:number }
class X { static foo: number }
class X { static foo :number }
class X { static foo : number }
declare class Foo { static bar:number; }
declare class Foo { static bar :number; }
declare class Foo { static bar: number; }
declare class Foo { static bar : number; }
class X { +foo: string }
class X { static +foo: string }
class X { +foo : string }
class X { static +foo : string }
type X = { foo: string }
type X = { foo : string }
type X = { foo?: string }
type X = { foo ?: string }
type X = { foo? : string }
type X = { +foo: string }
type X = { +foo?: string }
type X = { +foo : string }
type X = { +foo? : string }
type X = { [a : b] : c }
type X = { [a:b]:c }
type X = { [string] : c }
type X = { [string]:c }
type X = { +[a : b] : c }
type X = { +[a:b]:c }
type X = { [a : (b)] : (c) }
type X = { [a:(b)]:(c) }
const x = ({}:{})
const x = ({} :{})
((x): string)
((x) : string)
const x :number = 7;
let x :number = 42;
var x :number = 42;
spread-exact-type
Enforce object types, that are spread to be exact type explicitly.
The following patterns are considered problems:
type bar = {...{test: string}}
type foo = {test: number}; type bar = {...foo}
The following patterns are not considered problems:
type bar = {...$Exact<{test: string}>}
type foo = {test: number}; type bar = {...$Exact<foo>}
type-id-match
Enforces a consistent naming pattern for type aliases.
Options
This rule requires a text RegExp:
{
"rules": {
"ft-flow/type-id-match": [
2,
"^([A-Z][a-z0-9]*)+Type$"
]
}
}
'^([A-Z][a-z0-9]*)+Type$'
is the default pattern.
The following patterns are considered problems:
opaque type foo = {};
type foo = {};
type FooType = {};
The following patterns are not considered problems:
type FooType = {};
type foo = {};
type foo = {};
type-import-style
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces a particular style for type imports:
// 'identifier' style
import {type T, type U, type V} from '...';
// 'declaration' style
import type {T, U, V} from '...';
Options
The rule has a string option:
"identifier"
(default): Enforces that type imports are all in the
'identifier' style."declaration"
: Enforces that type imports are all in the 'declaration'
style.
This rule has an object option:
ignoreTypeDefault
- if true
, when in "identifier" mode, default type imports will be ignored. Default is false
.
The following patterns are considered problems:
import type {A, B} from 'a';
import type {A, B} from 'a';
import type {A, B as C} from 'a';
import type A from 'a';
import {type A, type B} from 'a';
The following patterns are not considered problems:
import {type A, type B} from 'a';
import {type A, type B} from 'a';
import type {A, B} from 'a';
import typeof * as A from 'a';
import type A from 'a';
declare module "m" { import type A from 'a'; }
union-intersection-spacing
The --fix
option on the command line automatically fixes problems reported by this rule.
Enforces consistent spacing around union and intersection type separators (|
and &
).
This rule takes one argument. If it is 'always'
then a problem is raised when there is no space around the separator. If it is 'never'
then a problem is raised when there is a space around the separator.
The default value is 'always'
.
The following patterns are considered problems:
type X = string| number;
type X = string| number;
type X = string |number;
type X = string|number;
type X = {x: string}|{y: number};
type X = string | number |boolean;
type X = string|number|boolean;
type X = (string)| number;
type X = ((string))|(number | foo);
type X = string |number;
type X = string| number;
type X = string& number;
type X = string& number;
type X = string &number;
type X = {x: string}&{y: number};
type X = string&number;
type X = string & number &boolean;
type X = string&number&boolean;
type X = (string)& number;
type X = ((string))&(number & foo);
type X = string &number;
type X = string& number;
The following patterns are not considered problems:
type X = string | number;
type X = string | number | boolean;
type X = (string) | number;
type X = ((string)) | (number | foo);
type X = string|number
type X =
| string
| number
function x() {
type X =
| string
| number
}
type X = string| number;
type X = string & number;
type X = string & number & boolean;
type X = (string) & number;
type X = ((string)) & (number & foo);
type X = string&number
type X =
& string
& number
function x() {
type X =
& string
& number
}
type X = string& number;
use-flow-type
@deprecated rule that is no longer needed with the current recommended config but kept around in case people want to continue using it with @babel/eslint-parser
such as the babel-parser
extension.
Marks Flow type alias declarations as used.
Used to suppress no-unused-vars
errors that are triggered by type aliases.
The following patterns are not considered problems:
declare class A {}
declare function A(): Y
declare module A {}
declare module A { declare var a: Y }
declare var A: Y
import type A from "a"; type X<B = ComponentType<A>> = { b: B }; let x: X; console.log(x);
import type A from "a"; type X<B = A<string>> = { b: B }; let x: X; console.log(x);
use-read-only-spread
Warns against accidentally creating an object which is no longer read-only because of how spread operator works in Flow. Imagine the following code:
type INode = {|
+type: string,
|};
type Identifier = {|
...INode,
+name: string,
|};
You might expect the identifier name to be read-only, however, that's not true (flow.org/try):
const x: Identifier = { name: '', type: '' };
x.type = 'must NOT be writable!'; // No Flow error
x.name = 'must NOT be writable!'; // No Flow error
This rule suggests to use $ReadOnly<…>
to prevent accidental loss of readonly-ness:
type Identifier = $ReadOnly<{|
...INode,
+name: string,
|}>;
const x: Identifier = { name: '', type: '' };
x.type = 'must NOT be writable!'; // $FlowExpectedError[cannot-write]
x.name = 'must NOT be writable!'; // $FlowExpectedError[cannot-write]
The following patterns are considered problems:
type INode = {||};
type Identifier = {|
...INode,
+aaa: string,
|};
type INode = {||};
type Identifier = {|
...INode,
+aaa: string,
+bbb: string,
|};
The following patterns are not considered problems:
type INode = {||};
type Identifier = {|
...INode,
name: string,
|};
type INode = {||};
type Identifier = {|
...INode,
name: string,
+surname: string,
|};
type Identifier = {|
+name: string,
|};
type INode = {||};
type Identifier = $ReadOnly<{|
...INode,
+name: string,
|}>;
type INode = {||};
type Identifier = $ReadOnly<{|
...INode,
name: string,
|}>;
type INode = {||};
type Identifier = $ReadOnly<{|
...INode,
-name: string,
|}>;
valid-syntax
Deprecated Babylon (the Babel parser) v6.10.0 fixes parsing of the invalid syntax this plugin warned against.
Checks for simple Flow syntax errors.
The following patterns are not considered problems:
function x(foo: string = "1") {}
function x(foo: Type = bar()) {}