UNPKG

eslint-plugin-flowtype

Version:
2,131 lines (1,560 loc) 177 kB
<a name="eslint-plugin-flowtype"></a> # eslint-plugin-flowtype [![NPM version](http://img.shields.io/npm/v/eslint-plugin-flowtype.svg?style=flat-square)](https://www.npmjs.org/package/eslint-plugin-flowtype) [![Travis build status](http://img.shields.io/travis/gajus/eslint-plugin-flowtype/master.svg?style=flat-square)](https://travis-ci.com/github/gajus/eslint-plugin-flowtype) [![js-canonical-style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical) [Flow type](http://flowtype.org/) linting rules for ESLint. * [eslint-plugin-flowtype](#eslint-plugin-flowtype) * [Installation](#eslint-plugin-flowtype-installation) * [Configuration](#eslint-plugin-flowtype-configuration) * [Shareable configurations](#eslint-plugin-flowtype-configuration-shareable-configurations) * [Community maintained configurations](#eslint-plugin-flowtype-configuration-community-maintained-configurations) * [Settings](#eslint-plugin-flowtype-settings) * [`onlyFilesWithFlowAnnotation`](#eslint-plugin-flowtype-settings-onlyfileswithflowannotation) * [Rules](#eslint-plugin-flowtype-rules) * [`array-style-complex-type`](#eslint-plugin-flowtype-rules-array-style-complex-type) * [`array-style-simple-type`](#eslint-plugin-flowtype-rules-array-style-simple-type) * [`arrow-parens`](#eslint-plugin-flowtype-rules-arrow-parens) * [`boolean-style`](#eslint-plugin-flowtype-rules-boolean-style) * [`define-flow-type`](#eslint-plugin-flowtype-rules-define-flow-type) * [`delimiter-dangle`](#eslint-plugin-flowtype-rules-delimiter-dangle) * [`enforce-line-break`](#eslint-plugin-flowtype-rules-enforce-line-break) * [`generic-spacing`](#eslint-plugin-flowtype-rules-generic-spacing) * [`interface-id-match`](#eslint-plugin-flowtype-rules-interface-id-match) * [`newline-after-flow-annotation`](#eslint-plugin-flowtype-rules-newline-after-flow-annotation) * [`no-dupe-keys`](#eslint-plugin-flowtype-rules-no-dupe-keys) * [`no-duplicate-type-union-intersection-members`](#eslint-plugin-flowtype-rules-no-duplicate-type-union-intersection-members) * [`no-existential-type`](#eslint-plugin-flowtype-rules-no-existential-type) * [`no-flow-fix-me-comments`](#eslint-plugin-flowtype-rules-no-flow-fix-me-comments) * [`no-internal-flow-type`](#eslint-plugin-flowtype-rules-no-internal-flow-type) * [`no-mixed`](#eslint-plugin-flowtype-rules-no-mixed) * [`no-mutable-array`](#eslint-plugin-flowtype-rules-no-mutable-array) * [`no-primitive-constructor-types`](#eslint-plugin-flowtype-rules-no-primitive-constructor-types) * [`no-types-missing-file-annotation`](#eslint-plugin-flowtype-rules-no-types-missing-file-annotation) * [`no-unused-expressions`](#eslint-plugin-flowtype-rules-no-unused-expressions) * [`no-weak-types`](#eslint-plugin-flowtype-rules-no-weak-types) * [`object-type-curly-spacing`](#eslint-plugin-flowtype-rules-object-type-curly-spacing) * [`object-type-delimiter`](#eslint-plugin-flowtype-rules-object-type-delimiter) * [`quotes`](#eslint-plugin-flowtype-rules-quotes) * [`require-compound-type-alias`](#eslint-plugin-flowtype-rules-require-compound-type-alias) * [`require-exact-type`](#eslint-plugin-flowtype-rules-require-exact-type) * [`require-indexer-name`](#eslint-plugin-flowtype-rules-require-indexer-name) * [`require-inexact-type`](#eslint-plugin-flowtype-rules-require-inexact-type) * [`require-parameter-type`](#eslint-plugin-flowtype-rules-require-parameter-type) * [`require-readonly-react-props`](#eslint-plugin-flowtype-rules-require-readonly-react-props) * [`require-return-type`](#eslint-plugin-flowtype-rules-require-return-type) * [`require-types-at-top`](#eslint-plugin-flowtype-rules-require-types-at-top) * [`require-valid-file-annotation`](#eslint-plugin-flowtype-rules-require-valid-file-annotation) * [`require-variable-type`](#eslint-plugin-flowtype-rules-require-variable-type) * [`semi`](#eslint-plugin-flowtype-rules-semi) * [`sort-keys`](#eslint-plugin-flowtype-rules-sort-keys) * [`sort-type-union-intersection-members`](#eslint-plugin-flowtype-rules-sort-type-union-intersection-members) * [`space-after-type-colon`](#eslint-plugin-flowtype-rules-space-after-type-colon) * [`space-before-generic-bracket`](#eslint-plugin-flowtype-rules-space-before-generic-bracket) * [`space-before-type-colon`](#eslint-plugin-flowtype-rules-space-before-type-colon) * [`spread-exact-type`](#eslint-plugin-flowtype-rules-spread-exact-type) * [`type-id-match`](#eslint-plugin-flowtype-rules-type-id-match) * [`type-import-style`](#eslint-plugin-flowtype-rules-type-import-style) * [`union-intersection-spacing`](#eslint-plugin-flowtype-rules-union-intersection-spacing) * [`use-flow-type`](#eslint-plugin-flowtype-rules-use-flow-type) * [`use-read-only-spread`](#eslint-plugin-flowtype-rules-use-read-only-spread) * [`valid-syntax`](#eslint-plugin-flowtype-rules-valid-syntax) <a name="eslint-plugin-flowtype-installation"></a> ## Installation ```bash npm install eslint --save-dev npm install @babel/eslint-parser --save-dev npm install eslint-plugin-flowtype --save-dev ``` <a name="eslint-plugin-flowtype-configuration"></a> ## Configuration 1. Set `parser` property to `@babel/eslint-parser`. 1. Add `plugins` section and specify `eslint-plugin-flowtype` as a plugin. 1. Enable rules. <!-- --> ```json { "parser": "@babel/eslint-parser", "plugins": [ "flowtype" ], "rules": { "flowtype/boolean-style": [ 2, "boolean" ], "flowtype/define-flow-type": 1, "flowtype/delimiter-dangle": [ 2, "never" ], "flowtype/generic-spacing": [ 2, "never" ], "flowtype/interface-id-match": [ 2, "^([A-Z][a-z0-9]+)+Type$" ], "flowtype/no-mixed": 2, "flowtype/no-primitive-constructor-types": 2, "flowtype/no-types-missing-file-annotation": 2, "flowtype/no-weak-types": 2, "flowtype/object-type-delimiter": [ 2, "comma" ], "flowtype/require-parameter-type": 2, "flowtype/require-readonly-react-props": 0, "flowtype/require-return-type": [ 2, "always", { "annotateUndefined": "never" } ], "flowtype/require-valid-file-annotation": 2, "flowtype/semi": [ 2, "always" ], "flowtype/space-after-type-colon": [ 2, "always" ], "flowtype/space-before-generic-bracket": [ 2, "never" ], "flowtype/space-before-type-colon": [ 2, "never" ], "flowtype/type-id-match": [ 2, "^([A-Z][a-z0-9]+)+Type$" ], "flowtype/union-intersection-spacing": [ 2, "always" ], "flowtype/use-flow-type": 1, "flowtype/valid-syntax": 1 }, "settings": { "flowtype": { "onlyFilesWithFlowAnnotation": false } } } ``` <a name="eslint-plugin-flowtype-configuration-shareable-configurations"></a> ### Shareable configurations <a name="eslint-plugin-flowtype-configuration-shareable-configurations-recommended"></a> #### Recommended This plugin exports a [recommended configuration](./src/configs/recommended.json) that enforces Flow type good practices. To enable this configuration use the extends property in your `.eslintrc` config file: ```json { "extends": [ "plugin:flowtype/recommended" ], "plugins": [ "flowtype" ] } ``` See [ESLint documentation](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information about extending configuration files. <a name="eslint-plugin-flowtype-configuration-community-maintained-configurations"></a> ### Community maintained configurations The following are third-party submitted/ maintained configurations of `eslint-plugin-flowtype`: * https://github.com/wemake-services/eslint-config-flowtype-essential <a name="eslint-plugin-flowtype-settings"></a> ## Settings <a name="eslint-plugin-flowtype-settings-onlyfileswithflowannotation"></a> ### <code>onlyFilesWithFlowAnnotation</code> When `true`, only checks files with a [`@flow` annotation](http://flowtype.org/docs/about-flow.html#gradual) in the first comment. ```js { "settings": { "flowtype": { "onlyFilesWithFlowAnnotation": true } } } ``` <a name="eslint-plugin-flowtype-rules"></a> ## Rules <!-- Rules are sorted alphabetically. --> <a name="eslint-plugin-flowtype-rules-array-style-complex-type"></a> ### <code>array-style-complex-type</code> _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: * [Maybe type](https://flow.org/en/docs/types/maybe/) * [Function type](https://flow.org/en/docs/types/functions/) * [Object type](https://flow.org/en/docs/types/objects/) * [Tuple type](https://flow.org/en/docs/types/tuples/) * [Union type](https://flow.org/en/docs/types/unions/) * [Intersection type](https://flow.org/en/docs/types/intersections/) 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: ```js 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: ```js type X = Array<?string> // Options: ["verbose"] type X = Array<?string> // Options: ["shorthand"] type X = (?string)[] // Options: ["shorthand"] type X = Array<string> // Options: ["shorthand"] // Settings: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} type X = Array<?string> ``` <a name="eslint-plugin-flowtype-rules-array-style-simple-type"></a> ### <code>array-style-simple-type</code> _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: * [Primitive types](https://flow.org/en/docs/types/primitives/) * [Literal types](https://flow.org/en/docs/types/literals/) * [Mixed type](https://flow.org/en/docs/types/mixed/) * [Any type](https://flow.org/en/docs/types/any/) * [Class type](https://flow.org/en/docs/types/classes/) * [Generic type](https://flow.org/en/docs/types/generics/) * Array type [shorthand notation](https://flow.org/en/docs/types/arrays/#toc-array-type-shorthand-syntax) 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: ```js 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: ```js 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: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} type X = string[] type X = Array type X = typeof Array ``` <a name="eslint-plugin-flowtype-rules-arrow-parens"></a> ### <code>arrow-parens</code> _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: ```js 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: ```js () => {} (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" ``` <a name="eslint-plugin-flowtype-rules-boolean-style"></a> ### <code>boolean-style</code> _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: ```js 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: ```js type X = boolean // Options: ["boolean"] type X = boolean // Options: ["bool"] type X = bool // Options: ["boolean"] // Settings: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} type X = bool ``` <a name="eslint-plugin-flowtype-rules-define-flow-type"></a> ### <code>define-flow-type</code> Marks Flow type identifiers as defined. Used to suppress [`no-undef`](http://eslint.org/docs/rules/no-undef) reporting of type identifiers. The following patterns are not considered problems: ```js 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: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} /** * Copyright 2019 no corp * @flow */ type Foo = $ReadOnly<{}> // 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: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} /** * Copyright 2019 no corp * @flow */ type Foo = $ReadOnly<{}> // Additional rules: {"no-undef":2,"no-use-before-define":[2,"nofunc"]} ``` <a name="eslint-plugin-flowtype-rules-delimiter-dangle"></a> ### <code>delimiter-dangle</code> _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: 1. The first argument is for Object and Tuple annotations. The default value is `'never'`. 2. The second argument is used for Interface annotations. This defaults to the value of the first argument. 3. 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: ```js 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: ```js 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 = [] ``` <a name="eslint-plugin-flowtype-rules-enforce-line-break"></a> ### <code>enforce-line-break</code> This rule enforces line breaks between type definitions. The following patterns are considered problems: ```js 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: ```js 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 ``` <a name="eslint-plugin-flowtype-rules-generic-spacing"></a> ### <code>generic-spacing</code> _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: ```js 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: ```js 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))) > ``` <a name="eslint-plugin-flowtype-rules-interface-id-match"></a> ### <code>interface-id-match</code> Enforces a consistent naming pattern for interfaces. <a name="eslint-plugin-flowtype-rules-interface-id-match-options"></a> #### Options This rule requires a text RegExp: ```js { "rules": { "flowtype/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: ```js 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: ```js interface FooType {}; // Options: ["^foo$"] interface foo {}; // Settings: {"flowtype":{"onlyFilesWithFlowAnnotation":true}} interface foo {}; ``` <a name="eslint-plugin-flowtype-rules-newline-after-flow-annotation"></a> ### <code>newline-after-flow-annotation</code> This rule requires an empty line after the Flow annotation. <a name="eslint-plugin-flowtype-rules-newline-after-flow-annotation-options-1"></a> #### 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 ```js { "rules": { "flowtype/newline-after-flow-annotation": [ 2, "always" ] } } ``` The following patterns are considered problems: ```js // @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 ``` The following patterns are not considered problems: ```js // Options: ["always"] // @flow import Foo from './foo'; // Options: ["always-windows"] // @flow import Foo from './foo'; // Options: ["never"] // @flow import Foo from './foo'; ``` <a name="eslint-plugin-flowtype-rules-no-dupe-keys"></a> ### <code>no-dupe-keys</code> Checks for duplicate properties in Object annotations. This rule mirrors ESLint's [no-dupe-keys](http://eslint.org/docs/rules/no-dupe-keys) rule. ```js { "rules": { "flowtype/no-dupe-keys": 2 } } ``` The following patterns are considered problems: ```js 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: ```js type FooType = { a: number, b: string, c: number } // Settings: {"flowtype":{"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; } ``` <a name="eslint-plugin-flowtype-rules-no-duplicate-type-union-intersection-members"></a> ### <code>no-duplicate-type-union-intersection-members</code> _The `--fix` option on the command line automatically fixes problems reported by this rule._ Checks for duplicate members of a type union/intersection. <a name="eslint-plugin-flowtype-rules-no-duplicate-type-union-intersection-members-options-2"></a> #### 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. ```js { "rules": { "flowtype/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. ```js { "rules": { "flowtype/no-duplicate-type-union-intersection-members": [ 2, { "checkUnions": true } ] } } ``` The following patterns are considered problems: ```js type A = 1 | 2 | 3 | 1; // Message: Duplicate union member found "1". type B = 'foo' | 'bar' | 'foo'; /