eslint-plugin-ft-flow
v3.0.11
Published
Flowtype linting rules for ESLint by flow-typed
Downloads
3,156,810
Maintainers
Readme
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
- Configuration
- Settings
- Rules
array-style-complex-type
array-style-simple-type
arrow-parens
boolean-style
define-flow-type
delimiter-dangle
enforce-line-break
enforce-suppression-code
generic-spacing
interface-id-match
newline-after-flow-annotation
no-dupe-keys
no-duplicate-type-union-intersection-members
no-existential-type
no-flow-fix-me-comments
no-flow-suppressions-in-strict-files
no-internal-flow-type
no-mixed
no-mutable-array
no-primitive-constructor-types
no-types-missing-file-annotation
no-unused-expressions
no-weak-types
object-type-curly-spacing
object-type-delimiter
quotes
require-compound-type-alias
require-exact-type
require-indexer-name
require-inexact-type
require-parameter-type
require-readonly-react-props
require-return-type
require-types-at-top
require-valid-file-annotation
require-variable-type
semi
sort-keys
sort-type-union-intersection-members
space-after-type-colon
space-before-generic-bracket
space-before-type-colon
spread-exact-type
type-id-match
type-import-style
union-intersection-spacing
use-flow-type
use-read-only-spread
valid-syntax
Installation
npm install eslint-plugin-ft-flow eslint hermes-eslint --save-dev
# or with yarn
yarn add -D eslint-plugin-ft-flow eslint hermes-eslint
# or with pnpm
pnpm add -D eslint-plugin-ft-flow eslint hermes-eslint
Configuration
- Set
parser
property tohermes-eslint
. - Add
plugins
section and specifyft-flow
as a plugin. - Enable rules.
{
"parser": "hermes-eslint",
"plugins": ["ft-flow"],
"rules": {
"ft-flow/boolean-style": [2, "boolean"]
// ... more rules
},
"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)[]
// Message: Use "Array<?string>", not "(?string)[]"
// Options: ["verbose"]
type X = (?string)[]
// Message: Use "Array<?string>", not "(?string)[]"
// Options: ["shorthand"]
type X = Array<?string>
// Message: Use "(?string)[]", not "Array<?string>"
// Options: ["shorthand"]
type X = Array<{foo: string}>
// Message: Use "{foo: string}[]", not "Array<{foo: string}>"
type X = (string | number)[]
// Message: Use "Array<string | number>", not "(string | number)[]"
type X = (string & number)[]
// Message: Use "Array<string & number>", not "(string & number)[]"
type X = [string, number][]
// Message: Use "Array<[string, number]>", not "[string, number][]"
type X = {foo: string}[]
// Message: Use "Array<{foo: string}>", not "{foo: string}[]"
type X = (string => number)[]
// Message: Use "Array<string => number>", not "(string => number)[]"
type X = {
foo: string,
bar: number
}[]
// Message: Use "Array<{ foo: string, bar: number }>", not "{ foo: string, bar: number }[]"
type X = {
foo: string,
bar: number,
quo: boolean,
hey: Date
}[]
// Message: Use "Array<Type>", not "Type[]"
The following patterns are not considered problems:
type X = Array<?string>
// Options: ["verbose"]
type X = Array<?string>
// Options: ["shorthand"]
type X = (?string)[]
// Options: ["shorthand"]
type X = Array<string>
// Options: ["shorthand"]
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
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[]
// Message: Use "Array<string>", not "string[]"
// Options: ["verbose"]
type X = string[]
// Message: Use "Array<string>", not "string[]"
// Options: ["shorthand"]
type X = Array<string>
// Message: Use "string[]", not "Array<string>"
type X = Date[]
// Message: Use "Array<Date>", not "Date[]"
type X = Promise<string>[]
// Message: Use "Array<Promise<string>>", not "Promise<string>[]"
type X = $Keys<{foo: string}>[]
// Message: Use "Array<$Keys<{foo: string}>>", not "$Keys<{foo: string}>[]"
type X = any[]
// Message: Use "Array<any>", not "any[]"
type X = mixed[]
// Message: Use "Array<mixed>", not "mixed[]"
type X = void[]
// Message: Use "Array<void>", not "void[]"
type X = null[]
// Message: Use "Array<null>", not "null[]"
type X = Promise<{
foo: string,
bar: number
}>[]
// Message: Use "Array<Promise<{ foo: string, bar: number }>>", not "Promise<{ foo: string, bar: number }>[]"
type X = Promise<{
foo: string,
bar: number,
quo: boolean
}>[]
// Message: Use "Array<Type>", not "Type[]"
The following patterns are not considered problems:
type X = Array<string>
// Options: ["verbose"]
type X = Array<string>
// Options: ["shorthand"]
type X = string[]
type X = Array<Array<string>>
// Options: ["verbose"]
type X = (?string)[]
// Options: ["verbose"]
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
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 => {}
// Message: undefined
a => a
// Message: undefined
a => {
}
// Message: undefined
a.then(foo => {});
// Message: undefined
a.then(foo => a);
// Message: undefined
a(foo => { if (true) {}; });
// Message: undefined
a(async foo => { if (true) {}; });
// Message: undefined
// Options: ["as-needed"]
(a) => a
// Message: undefined
// Options: ["as-needed"]
(a,) => a
// Message: undefined
// Options: ["as-needed"]
async (a) => a
// Message: undefined
// Options: ["as-needed"]
async(a) => a
// Message: undefined
// Options: ["as-needed",{"requireForBlockBody":true}]
a => {}
// Message: undefined
// Options: ["as-needed",{"requireForBlockBody":true}]
(a) => a
// Message: undefined
// Options: ["as-needed",{"requireForBlockBody":true}]
async a => {}
// Message: undefined
// Options: ["as-needed",{"requireForBlockBody":true}]
async (a) => a
// Message: undefined
// Options: ["as-needed",{"requireForBlockBody":true}]
async(a) => a
// Message: undefined
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) {}; });
// Options: ["always"]
() => {}
// Options: ["always"]
(a) => {}
// Options: ["always"]
(a) => a
// Options: ["always"]
(a) => {
}
// Options: ["always"]
a.then((foo) => {});
// Options: ["always"]
a.then((foo) => { if (true) {}; });
// Options: ["always"]
a.then(async (foo) => { if (true) {}; });
// Options: ["as-needed"]
() => {}
// Options: ["as-needed"]
a => {}
// Options: ["as-needed"]
a => a
// Options: ["as-needed"]
([a, b]) => {}
// Options: ["as-needed"]
({ a, b }) => {}
// Options: ["as-needed"]
(a = 10) => {}
// Options: ["as-needed"]
(...a) => a[0]
// Options: ["as-needed"]
(a, b) => {}
// Options: ["as-needed"]
async ([a, b]) => {}
// Options: ["as-needed"]
async (a, b) => {}
// Options: ["as-needed"]
(a: T) => a
// Options: ["as-needed"]
(a): T => a
// Options: ["as-needed",{"requireForBlockBody":true}]
() => {}
// Options: ["as-needed",{"requireForBlockBody":true}]
a => a
// Options: ["as-needed",{"requireForBlockBody":true}]
([a, b]) => {}
// Options: ["as-needed",{"requireForBlockBody":true}]
([a, b]) => a
// Options: ["as-needed",{"requireForBlockBody":true}]
({ a, b }) => {}
// Options: ["as-needed",{"requireForBlockBody":true}]
({ a, b }) => a + b
// Options: ["as-needed",{"requireForBlockBody":true}]
(a = 10) => {}
// Options: ["as-needed",{"requireForBlockBody":true}]
(...a) => a[0]
// Options: ["as-needed",{"requireForBlockBody":true}]
(a, b) => {}
// Options: ["as-needed",{"requireForBlockBody":true}]
a => ({})
// Options: ["as-needed",{"requireForBlockBody":true}]
async a => ({})
// Options: ["as-needed",{"requireForBlockBody":true}]
async a => a
// Options: ["as-needed",{"requireForBlockBody":true}]
(a: T) => a
// Options: ["as-needed",{"requireForBlockBody":true}]
(a): T => a
// Options: ["always",{"requireForBlockBody":true}]
<T>(a: T) => a
// Options: ["as-needed",{"requireForBlockBody":false}]
<T>(a: T) => { return a; }
// Options: ["always",{"requireForBlockBody":true}]
<T>(a: T) => { return a; }
// Options: ["as-needed",{"requireForBlockBody":true}]
<T>(a: T) => { return a; }
// Options: ["as-needed",{"requireForBlockBody":true}]
(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
// Message: Use "boolean", not "bool"
// Options: ["boolean"]
type X = bool
// Message: Use "boolean", not "bool"
// Options: ["bool"]
type X = boolean
// Message: Use "bool", not "boolean"
The following patterns are not considered problems:
type X = boolean
// Options: ["boolean"]
type X = boolean
// Options: ["bool"]
type X = bool
// Options: ["boolean"]
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
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 thebabel-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
// Additional rules: {"no-undef":2}
var a: AType; var b: AType
// Additional rules: {"no-undef":2}
var a; (a: AType)
// Additional rules: {"no-undef":2}
var a: AType<BType>
// Additional rules: {"no-undef":2}
type A = AType
// Additional rules: {"no-undef":2}
declare type A = number
// Additional rules: {"no-undef":2}
opaque type A = AType
// Additional rules: {"no-undef":2}
function f(a: AType) {}
// Additional rules: {"no-undef":2}
function f(a: AType.a) {}
// Additional rules: {"no-undef":2}
function f(a: AType.a.b) {}
// Additional rules: {"no-undef":2}
function f(a): AType {}; var a: AType
// Additional rules: {"no-undef":2}
function f(a): AType {}
// Additional rules: {"no-undef":2}
class C { a: AType }
// Additional rules: {"no-undef":2}
class C { a: AType.a }
// Additional rules: {"no-undef":2}
class C { a: AType.a.b }
// Additional rules: {"no-undef":2}
class C implements AType {}
// Additional rules: {"no-undef":2}
declare interface A {}
// Additional rules: {"no-undef":2}
({ a: ({b() {}}: AType) })
// Additional rules: {"no-undef":2}
type X = {Y<AType>(): BType}
// Additional rules: {"no-undef":2}
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
/**
* Copyright 2019 no corp
* @flow
*/
type Foo = $ReadOnly<{}>
// Additional rules: {"no-undef":2}
enum Status { Active, Paused }
// Additional rules: {"no-undef":2}
enum Status { Active = 'active', Paused = 'paused' }
// Additional rules: {"no-undef":2}
enum Status { Active = 1, Paused = 2 }
// Additional rules: {"no-undef":2}
var a: AType
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
var a: AType; var b: AType
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
var a; (a: AType)
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
var a: AType<BType>
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
type A = AType
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
declare type A = number
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
opaque type A = AType
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
function f(a: AType) {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
function f(a: AType.a) {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
function f(a: AType.a.b) {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
function f(a): AType {}; var a: AType
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
function f(a): AType {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
class C { a: AType }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
class C { a: AType.a }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
class C { a: AType.a.b }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
class C implements AType {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
declare interface A {}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
({ a: ({b() {}}: AType) })
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
type X = {Y<AType>(): BType}
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
/**
* Copyright 2019 no corp
* @flow
*/
type Foo = $ReadOnly<{}>
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
enum Status { Active, Paused }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
enum Status { Active = 'active', Paused = 'paused' }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
enum Status { Active = 1, Paused = 2 }
// Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]}
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, }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = { foo: string, }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = { foo: string; }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = {
foo: string,
}
// Message: Unexpected trailing delimiter
// Options: ["always"]
type X = { foo: string }
// Message: Missing trailing delimiter
// Options: ["always"]
type X = {
foo: string
}
// Message: Missing trailing delimiter
// Options: ["always-multiline"]
type X = { foo: string, }
// Message: Unexpected trailing delimiter
// Options: ["always-multiline"]
type X = {
foo: string
}
// Message: Missing trailing delimiter
// Options: ["only-multiline"]
type X = { foo: string; }
// Message: Unexpected trailing delimiter
// Options: ["always","never"]
interface X { foo: string; }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = { [key: string]: number, }
// Message: Unexpected trailing delimiter
// Options: ["always"]
type X = { [key: string]: number }
// Message: Missing trailing delimiter
// Options: ["always-multiline"]
type X = { [key: string]: number, }
// Message: Unexpected trailing delimiter
// Options: ["always-multiline"]
type X = {
[key: string]: number
}
// Message: Missing trailing delimiter
// Options: ["only-multiline"]
type X = { [key: string]: number; }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = { [key: string]: number, foo: string, }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = {
[key: string]: number,
foo: string,
}
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = {
[key: string]: number,
aReallyLongPropertyNameHere: string,
}
// Message: Unexpected trailing delimiter
// Options: ["always"]
type X = { [key: string]: number, foo: string }
// Message: Missing trailing delimiter
// Options: ["always"]
type X = {
[key: string]: number;
foo: string
}
// Message: Missing trailing delimiter
// Options: ["always-multiline"]
type X = { [key: string]: number, foo: string, }
// Message: Unexpected trailing delimiter
// Options: ["always-multiline"]
type X = {
[key: string]: number,
foo: string
}
// Message: Missing trailing delimiter
// Options: ["only-multiline"]
type X = { [key: string]: number, foo: string, }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = { foo: string, [key: string]: number, }
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = {
foo: string,
[key: string]: number,
}
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = {
aReallyLongPropertyNameHere: string,
[key: string]: number,
}
// Message: Unexpected trailing delimiter
// Options: ["always"]
type X = { foo: string, [key: string]: number }
// Message: Missing trailing delimiter
// Options: ["always"]
type X = { foo: string; [key: string]: number }
// Message: Missing trailing delimiter
// Options: ["always-multiline"]
type X = { foo: string, [key: string]: number; }
// Message: Unexpected trailing delimiter
// Options: ["always-multiline"]
type X = {
foo: string,
[key: string]: number
}
// Message: Missing trailing delimiter
// Options: ["only-multiline"]
type X = { foo: string, [key: string]: number; }
// Message: Unexpected trailing delimiter
type X = { ..., }
// Message: Unexpected trailing delimiter
type X = { ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = { ... }
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { ...; }
// Message: Unexpected trailing delimiter
type X = {
...,
}
// Message: Unexpected trailing delimiter
type X = {
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
...,
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = {
...
}
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = {
...
}
// Message: Missing trailing delimiter
type X = { foo: string, ..., }
// Message: Unexpected trailing delimiter
type X = { foo: string; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { foo: string, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { foo: string; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = { foo: string, ... }
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { foo: string, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { foo: string; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { foo: string, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { foo: string; ...; }
// Message: Unexpected trailing delimiter
type X = {
foo: string,
...,
}
// Message: Unexpected trailing delimiter
type X = {
foo: string;
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
foo: string,
...,
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
foo: string;
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = {
foo: string,
...
}
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = {
foo: string,
...
}
// Message: Missing trailing delimiter
type X = { [key: string]: number, ..., }
// Message: Unexpected trailing delimiter
type X = { [key: string]: number; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { [key: string]: number, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = { [key: string]: number; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = { [key: string]: number, ... }
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { [key: string]: number, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","always-multiline"]
type X = { [key: string]: number; ...; }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { [key: string]: number, ..., }
// Message: Unexpected trailing delimiter
// Options: ["never","never","only-multiline"]
type X = { [key: string]: number; ...; }
// Message: Unexpected trailing delimiter
type X = {
[key: string]: number,
...,
}
// Message: Unexpected trailing delimiter
type X = {
[key: string]: number;
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
[key: string]: number,
...,
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","never"]
type X = {
[key: string]: number;
...;
}
// Message: Unexpected trailing delimiter
// Options: ["never","never","always"]
type X = {
[key: string]: number,
...
}
// Message: Missing trailing delimiter
// Options: ["never","never","always-multiline"]
type X = {
[key: string]: number,
...
}
// Message: Missing trailing delimiter
type X = [string, number,]
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = [string, number,]
// Message: Unexpected trailing delimiter
// Options: ["never"]
type X = [
string,
number,
]
// Message: Unexpected trailing delimiter
// Options: ["always"]
type X = [string, number]
// Message: Missing trailing delimiter
// Options: ["always"]
type X = [
string,
number
]
// Message: Missing trailing delimiter
// Options: ["always-multiline"]
type X = [string, number,]
// Message: Unexpected trailing delimiter
// Options: ["always-multiline"]
type X = [
foo, string
]
// Message: Missing trailing delimiter
// Options: ["only-multiline"]
type X = [ number, string, ]
// Message: Unexpected trailing delimiter
The following patterns are not considered problems:
type X = { foo: string }
// Options: ["never"]
type X = { foo: string }
// Options: ["always"]
type X = { foo: string, }
// Options: ["always"]
type X = { foo: string; }
// Options: ["never"]
type X = {
foo: string
}
// Options: ["always"]
type X = {
foo: string,
}
// Options: ["always-multiline"]
type X = { foo: string }
// Options: ["always-multiline"]
type X = {
foo: string,
}
// Options: ["always-multiline"]
type X = {
foo: string;
}
// Options: ["only-multiline"]
type X = { foo: string }
// Options: ["only-multiline"]
type X = {
foo: string
}
// Options: ["only-multiline"]
type X = {
foo: string,
}
// Options: ["only-multiline"]
type X = {
foo: string;
}
// Options: ["never","always"]
interface X { foo: string; }
// Options: ["never"]
type X = {}
// Options: ["always"]
type X = {}
// Options: ["always-multiline"]
type X = {}
// Options: ["only-multiline"]
type X = {}
// Options: ["never"]
type X = { [key: string]: number }
// Options: ["always"]
type X = { [key: string]: number, }
// Options: ["always"]
type X = { [key: string]: number; }
// Options: ["always-multiline"]
type X = { [key: string]: number }
// Options: ["always-multiline"]
type X = {
[key: string]: number,
}
// Options: ["only-multiline"]
type X = {
[key: string]: number,
}
// Options: ["only-multiline"]
type X = {
[key: string]: number
}
// Options: ["only-multiline"]
type X = { [key: string]: number }
// Options: ["never"]
type X = { [key: string]: number, foo: string }
// Options: ["always"]
type X = { [key: string]: number, foo: string, }
// Options: ["always"]
type X = { [key: string]: number; foo: string; }
// Options: ["always-multiline"]
type X = { [key: string]: number, foo: string }
// Options: ["always-multiline"]
type X = {
[key: string]: number,
foo: string,
}
// Options: ["only-multiline"]
type X = {
[key: string]: number,
foo: string,
}
// Options: ["only-multiline"]
type X = {
[key: string]: number;
foo: string
}
// Options: ["only-multiline"]
type X = { [key: string]: number, foo: string }
// Options: ["never"]
type X = { foo: string, [key: string]: number }
// Options: ["always"]
type X = { foo: string, [key: string]: number, }
// Options: ["always"]
type X = { foo: string; [key: string]: number; }
// Options: ["always-multiline"]
type X = { foo: string, [key: string]: number }
// Options: ["always-multiline"]
type X = {
foo: string,
[key: string]: number,
}
// Options: ["only-multiline"]
type X = {
foo: string,
[key: string]: number,
}
// Options: ["only-multiline"]
type X = {
foo: string;
[key: string]: number
}
// Options: ["only-multiline"]
type X = { foo: string, [key: string]: number }
type X = { ... }
// Options: ["never","never","never"]
type X = { ... }
// Options: ["never","never","always"]
type X = { ..., }
// Options: ["never","never","always-multiline"]
type X = { ... }
// Options: ["never","never","only-multiline"]
type X = { ... }
type X = {
...
}
// Options: ["never","never","never"]
type X = {
...
}
// Options: ["never","never","always"]
type X = {
...,
}
// Options: ["never","never","always"]
type X = {
...;
}
// Options: ["never","never","always-multiline"]
type X = {
...,
}
// Options: ["never","never","always-multiline"]
type X = {
...;
}
// Options: ["never","never","only-multiline"]
type X = {
...
}
// Options: ["never","never","only-multiline"]
type X = {
...,
}
// Options: ["never","never","only-multiline"]
type X = {
...;
}
type X = { foo: string, ... }
// Options: ["never","never","never"]
type X = { foo: string, ... }
// Options: ["never","never","always"]
type X = { foo: string, ..., }
// Options: ["never","never","always"]
type X = { foo: string; ...; }
// Options: ["never","never","always-multiline"]
type X = { foo: string, ... }
// Options: ["never","never","only-multiline"]
type X = { foo: string, ... }
type X = {
foo: string,
...
}
// Options: ["never","never","never"]
type X = {
foo: string,
...
}
// Options: ["never","never","always"]
type X = {
foo: string,
...,
}
// Options: ["never","never","always"]
type X = {
foo: string;
...;
}
// Options: ["never","never","always-multiline"]
type X = {
foo: string,
...,
}
// Options: ["never","never","always-multiline"]
type X = {
foo: string;
...;
}
// Options: ["never","never","only-multiline"]
type X = {
foo: string,
...
}
// Options: ["never","never","only-multiline"]
type X = {
foo: string,
...,
}
// Options: ["never","never","only-multiline"]
type X = {
foo: string,
...;
}
// Options: ["never","never","never"]
type X = { [key: string]: number, ... }
// Options: ["never","never","always"]
type X = { [key: string]: number, ..., }
// Options: ["never","never","always"]
type X = { [key: string]: number; ...; }
// Options: ["never","never","always-multiline"]
type X = { [key: string]: number, ... }
// Options: ["never","never","only-multiline"]
type X = { [key: string]: number, ... }
// Options: ["never","never","never"]
type X = {
[key: string]: number,
...
}
// Options: ["never","never","always"]
type X = {
[key: string]: number,
...,
}
// Options: ["never","never","always"]
type X = {
[key: string]: number;
...;
}
// Options: ["never","never","always-multiline"]
type X = {
[key: string]: number,
...,
}
// Options: ["never","never","always-multiline"]
type X = {
[key: string]: number;
...;
}
// Options: ["never","never","only-multiline"]
type X = {
[key: string]: number,
...
}
// Options: ["never","never","only-multiline"]
type X = {
[key: string]: number,
...,
}
// Options: ["never","never","only-multiline"]
type X = {
[key: string]: number;
...;
}
type X = [string, number]
// Options: ["never"]
type X = [string, number]
// Options: ["never"]
type X = [
string,
number
]
// Options: ["always"]
type X = [string, number,]
// Options: ["always"]
type X = [
string,
number,
]
// Options: ["always-multiline"]
type X = [ foo, string ]
// Options: ["always-multiline"]
type X = [
foo, string,
]
// Options: ["only-multiline"]
type X = [ number, string ]
// Options: ["only-multiline"]
type X = [
number,
string
]
// Options: ["only-multiline"]
type X = [
number,
string,
]
// Options: ["never"]
type X = []
// Options: ["always"]
type X = []
// Options: ["always-multiline"]
type X = []
// Options: ["only-multiline"]
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;
// Message: New line required below type declaration
const foo = 6;
type hi = 2;
// Message: New line required above type declaration
const som = "jes";
// a comment
type fed = "hed";
// Message: New line required above type declaration
type som = "jes";
// a comment
const fed = "hed";
// Message: New line required below type declaration
type hello = 34;
const som = "jes";
type fed = "hed";
// Message: New line required below type declaration
// Message: New line required above type declaration
const a = 5;
export type hello = 34;
// Message: New line required above type declaration
const a = 5;
// a comment
export type hello = 34;
// Message: New line required above type declaration
const a = 5;
/**
* a jsdoc block
*/
type hello = 34;
// Message: New line required above type declaration
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");
// number or string
type Y = string | number;
// resting + sleep
type snooze = "dreaming" | "";
type Props = {
accountBalance: string | number,
accountNumber: string | number,
};
const x = 4;
const y = 489;
// Some Comment
type Props = {
accountBalance: string | number,
accountNumber: string | number,
};
type RoadT = "grass" | "gravel" | "cement";
// @flow
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:
// $FlowFixMe I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is missing a suppression error code. Please update this suppression to use an error code: $FlowFixMe[…]
// $FlowExpectedError I am doing something evil here
const text = 'HELLO';
// Message: $FlowExpectedError is missing a suppression error code. Please update this suppression to use an error code: $FlowExpectedError[…]
// $FlowIssue I am doing something evil here
const text = 'HELLO';
// Message: $FlowIssue is missing a suppression error code. Please update this suppression to use an error code: $FlowIssue[…]
// $FlowIgnore I am doing something evil here
const text = 'HELLO';
// Message: $FlowIgnore is missing a suppression error code. Please update this suppression to use an error code: $FlowIgnore[…]
/* $FlowIgnore I am doing something evil here */
// Message: $FlowIgnore is missing a suppression error code. Please update this suppression to use an error code: $FlowIgnore[…]
{ /* $FlowIgnore I am doing something evil here */ }
// Message: $FlowIgnore is missing a suppression error code. Please update this suppression to use an error code: $FlowIgnore[…]
/**
* $FlowIgnore I am doing something evil here
*/
// Message: $FlowIgnore is missing a suppression error code. Please update this suppression to use an error code: $FlowIgnore[…]
The following patterns are not considered problems:
// Just a random comment
//
const text = 'HELLO';
// $FlowFixMe[incompatible-call] TODO 48
const text = 'HELLO';
// $FlowExpectedError[incompatible-call] TODO 48
const text = 'HELLO';
// $FlowIssue[incompatible-call] TODO 48
const text = 'HELLO';
// $FlowIgnore[incompatible-call] TODO 48
const text = 'HELLO';
/* $FlowIgnore[incompatible-call] TODO 48 */
/**
* $FlowIgnore[incompatible-call] TODO 48
*/
/* $FlowIgnore[incompatible-call] TODO 48 */
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>
// Message: There must be no space at start of "Promise" generic type annotation
// Options: ["never"]
type X = Promise< string>
// Message: There must be no space at start of "Promise" generic type annotation
type X = FooBar<string >
// Message: There must be no space at end of "FooBar" generic type annotation
type X = Promise< string >
// Message: There must be no space at start of "Promise" generic type annotation
// Message: There must be no space at end of "Promise" generic type annotation
type X = Promise< (foo), bar, (((baz))) >
// Message: There must be no space at start of "Promise" generic type annotation
// Message: There must be no space at end of "Promise" generic type annotation
// Options: ["always"]
type X = Promise<string >
// Message: There must be a space at start of "Promise" generic type annotation
// Options: ["always"]
type X = FooBar< string>
// Message: There must be a space at end of "FooBar" generic type annotation
// Options: ["always"]
type X = Promise<string>
// Message: There must be a space at start of "Promise" generic type annotation
// Message: There must be a space at end of "Promise" generic type annotation
// Options: ["always"]
type X = Promise<(foo), bar, (((baz)))>
// Message: There must be a space at start of "Promise" generic type annotation
// Message: There must be a space at end of "Promise" generic type annotation
// Options: ["always"]
type X = FooBar< string >
// Message: There must be one space at start of "FooBar" generic type annotation
// Options: ["always"]
type X = FooBar< string >
// Message: There must be one space at end of "FooBar" generic type annotation
// Options: ["always"]
type X = Promise< (foo), bar, (((baz))) >
// Message: There must be one space at start of "Promise" generic type annotation
// Message: There must be one space at end of "Promise" generic type annotation
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)))
>
// Options: ["always"]
type X = Promise< string >
// Options: ["always"]
type X = Promise< (string) >
// Options: ["always"]
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{};
// Message: Interface identifier 'foo' does not match pattern '/^([A-Z][a-z0-9]*)+Type$/u'.
// Options: ["^foo$"]
interface FooType{};
// Message: Interface identifier 'FooType' does not match pattern '/^foo$/u'.
The following patterns are not considered problems:
interface FooType {};
// Options: ["^foo$"]
interface foo {};
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
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:
// @flow
import Foo from './foo';
// Message: Expected newline after flow annotation
// Options: ["always"]
// @flow
import Foo from './foo';
// Message: Expected newline after flow annotation
// Options: ["always-windows"]
// @flow
import Foo from './foo';
// Message: Expected newline after flow annotation
// Options: ["never"]
// @flow
// Message: Expected no newline after flow annotation
/*
* @flow
*
* something multi lined
*/
const text: string = 42;
// Message: Expected newline after flow annotation
The following patterns are not considered problems:
// Options: ["always"]
// @flow
import Foo from './foo';
// Options: ["always-windows"]
// @flow
import Foo from './foo';
// Options: ["never"]
// @flow
import Foo from './foo';
// Options: ["always"]
/*
* @flow
*
* something multi lined
*/
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 }
// Message: Duplicate property.
type f = { a: number, b: string, a: string }
// Message: Duplicate property.
type f = { get(key: "a"): string, get(key: "a"): string }
// Message: Duplicate property.
type f = { get(key: 1): string, get(key: 1): string }
// Message: Duplicate property.
type f = { get(key: 1.1): string, get(key: 1.1): string }
// Message: Duplicate property.
type f = { get(key: true): string, get(key: true): string }
// Message: Duplicate property.
type f = { get(key: {a: 1}): string, get(key: {a: 1}):string }
// Message: Duplicate property.
var a = "a"; type f = { get(key: a): string, get(key: a): string }
// Message: Duplicate property.
var b = 1; type f = { get(key: b): string, get(key: b): string }
// Message: Duplicate property.
var c = true; type f = { get(key: c): string, get(key: c): string }
// Message: Duplicate property.
var d = {}; type f = { get(key: d): string, get(key: d): string }
// Message: Duplicate property.
var e = []; type f = { get(key: e): string, get(key: e): string }
// Message: Duplicate property.
var e = [1, "a"]; type f = { get(key: e): string, get(key: e): string }
// Message: Duplicate property.
function fn() {}; type f = { get(key: fn): string, get(key: fn): string }
// Message: Duplicate property.
The following patterns are not considered problems:
type FooType = { a: number, b: string, c: number }
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
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;
// Message: Duplicate union member found "1".
type B = 'foo' | 'bar' | 'foo';
// Message: Duplicate union member found "'foo'".
type C = A | B | A | B;
// Message: Duplicate union member found "A".
// Message: Duplicate union member found "B".
type C = A & B & A & B;
// Message: Duplicate intersection member found "A".
// Message: Duplicate intersection member found "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 = *;
// Message: Unexpected use of existential type (*).
type T = U<*, *>;
// Message: Unexpected use of existential type (*).
// Message: Unexpected use of existential type (*).
const f: (*) => null = () => null;
// Message: Unexpected use of existential type (*).
The following patterns are not considered problems:
type T = string | null
no-flow-fix-me-comments
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:
// $FlowFixMe I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is treated as 'any' and must be fixed.
// Options: ["TODO [0-9]+"]
// $FlowFixMe I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is treated as 'any' and must be fixed. Fix it or match '/TODO [0-9]+/u'.
// Options: ["TODO [0-9]+"]
// $FlowFixMe TODO abc 47 I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is treated as 'any' and must be fixed. Fix it or match '/TODO [0-9]+/u'.
// $$FlowFixMeProps I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is treated as 'any' and must be fixed.
// Options: ["TODO [0-9]+"]
// $FlowFixMeProps I am doing something evil here
const text = 'HELLO';
// Message: $FlowFixMe is treated as 'any' and must be fixed. Fix it or match '/TODO [0-9]+/u'.
The following patterns are not considered problems:
const text = 'HELLO';
// Options: ["TODO [0-9]+"]
// $FlowFixMe TODO 48
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:
// Options: [{}]
// @flow strict
// $FlowFixMe
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{}]
// @flow strict-local
// $FlowFixMe
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{}]
// @flow strict
// $FlowExpectedError[xxx]
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{}]
/* @flow strict */
// $FlowExpectedError[xxx]
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{}]
/*
* @flow strict
*
* something multi lined
*/
// $FlowExpectedError[xxx]
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{}]
/*
* @flow strict
*
* something multi lined
*/
/* $FlowIgnore[xxx] */
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
// Options: [{"$FlowExpectedError":false}]
// @flow strict
// $FlowFixMe
const text: string = 42;
// Message: No suppression comments are allowed in "strict" Flow files. Either remove the error suppression, or lower the strictness of this module.
The following patterns are not considered problems:
// Options: [{}]
// @flow
// Error suppressions are fine in "normal" Flow files
// $FlowFixMe
const text: string = 42;
// Options: [{}]
// @flow strict
// Definitely nothing to suppress here
// ...
// Options: [{}]
// @flow strict-local
// Definitely nothing to suppress here
// ...
// Options: [{"$FlowExpectedError":false}]
// @flow strict
// $FlowExpectedError
const text: string = 42;
// Options: [{"$FlowExpectedError":false}]
// @flow strict-local
// $FlowExpectedError
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>
// Message: Type identifier 'React$AbstractComponent' is not allowed. Use 'React.AbstractComponent' instead.
type X = React$ChildrenArray<string>
// Message: Type identifier 'React$ChildrenArray' is not allowed. Use 'React.ChildrenArray' instead.
type X = React$ComponentType<Props>
// Message: Type identifier 'React$ComponentType' is not allowed. Use 'React.ComponentType' instead.
type X = React$Config<Prosp, DefaultProps>
// Message: Type identifier 'React$Config' is not allowed. Use 'React.Config' instead.
type X = React$Element<typeof Component>
// Message: Type identifier 'React$Element' is not allowed. Use 'React.Element' instead.
type X = React$ElementConfig<typeof Component>
// Message: Type identifier 'React$ElementConfig' is not allowed. Use 'React.ElementConfig' instead.
type X = React$ElementProps<typeof Component>
// Message: Type identifier 'React$ElementProps' is not allowed. Use 'React.ElementProps' instead.
type X = React$ElementRef<typeof Component>
// Message: Type identifier 'React$ElementRef' is not allowed. Use 'React.ElementRef' instead.
type X = React$ElementType
// Message: Type identifier 'React$ElementType' is not allowed. Use 'React.ElementType' instead.
type X = React$Key
// Message: Type identifier 'React$Key' is not allowed. Use 'React.Key' instead.
type X = React$Node
// Message: Type identifier 'React$Node' is not allowed. Use 'React.Node' instead.
type X = React$Ref<typeof Component>
// Message: Type identifier 'React$Ref' is not allowed. Use 'React.Ref' instead.
type X = React$StatelessFunctionalComponent<Props>
// Message: Type identifier 'React$StatelessFunctionalComponent' is not allowed. Use 'React.StatelessFunctionalComponent' instead.
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 {}
// Message: Unexpected use of mixed type
function foo(thing): Promise<mixed> {}
// Message: Unexpected use of mixed type
function foo(thing): Promise<Promise<mixed>> {}
// Message: Unexpected use of mixed type
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>
// Message: Use "$ReadOnlyArray" instead of "Array"
type X = string[]
// Message: Use "$ReadOnlyArray" instead of array shorthand notation
const values: Array<Array<string>> = [];
// Message: Use "$ReadOnlyArray" instead of "Array"
let values: Array<Array<string>>;
// Message: Use "$ReadOnlyArray" instead of "Array"
// Message: Use "$ReadOnlyArray" instead of "Array"
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
// Message: Unexpected use of Number constructor type.
type x = String
// Message: Unexpected use of String constructor type.
type x = Boolean
// Message: Unexpected use of Boolean constructor type.
type x = { a: Number }
// Message: Unexpected use of Number constructor type.
type x = { a: String }
// Message: Unexpected use of String constructor type.
type x = { a: Boolean }
// Message: Unexpected use of Boolean constructor type.
(x: Number) => {}
// Message: Unexpected use of Number constructor type.
(x: String) => {}
// Message: Unexpected use of String constructor type.
(x: Boolean) => {}
// Message: Unexpected use of Boolean constructor type.
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;
// Message: Type annotations require valid Flow declaration.
type FooType = number;
// Message: Type aliases require valid Flow declaration.
import type A from "a"
// Message: Type imports require valid Flow declaration.
import type {A} from "a"
// Message: Type imports require valid Flow declaration.
import {type A} from "a"
// Message: Type imports require valid Flow declaration.
export type {A} from "a"
// Message: Type exports require valid Flow declaration.
function t<T>(): T{}
// Message: Type annotations require valid Flow declaration.
// Settings: {"ft-flow":{"onlyFilesWithFlowAnnotation":true}}
const x: number = 42;
// Message: Type annotations require valid Flow declaration.
The following patterns are not considered problems:
// @flow
const x: number = 42;
/* @flow weak */
type FooType = number;
/* @noflow */
type FooType = number;
/* @noflow */
import type A from "a"
/* @noflow */
import {type A} from "a"
/* @noflow */
export type {A} from "a"
// an unrelated comment
// @flow
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;
c