diff --git a/.eslintrc.js b/.eslintrc.js index 45426c37acf..32a476969d3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,23 +21,12 @@ module.exports = { // our plugin :D // - '@typescript-eslint/ban-ts-ignore': 'error', - '@typescript-eslint/consistent-type-definitions': 'error', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-member-accessibility': 'off', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-inferrable-types': 'error', - '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], + '@typescript-eslint/no-explicit-any': 'error', '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-object-literal-type-assertion': 'off', - '@typescript-eslint/no-parameter-properties': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/prefer-includes': 'error', - '@typescript-eslint/prefer-regexp-exec': 'error', - '@typescript-eslint/prefer-string-starts-ends-with': 'error', + '@typescript-eslint/unbound-method': 'off', // // eslint base @@ -110,12 +99,12 @@ module.exports = { 'import/no-mutable-exports': 'error', // Prevent importing the default as if it were named 'import/no-named-default': 'error', - // Prohibit named exports // we want everything to be a named export - 'import/no-named-export': 'off', + // Prohibit named exports + 'import/no-named-export': 'off', // we want everything to be a named export // Forbid a module from importing itself 'import/no-self-import': 'error', - // Require modules with a single export to use a default export // we want everything to be named - 'import/prefer-default-export': 'off', + // Require modules with a single export to use a default export + 'import/prefer-default-export': 'off', // we want everything to be named }, parserOptions: { sourceType: 'module', diff --git a/.prettierrc b/.prettierrc.json similarity index 100% rename from .prettierrc rename to .prettierrc.json diff --git a/packages/eslint-plugin-tslint/src/custom-linter.ts b/packages/eslint-plugin-tslint/src/custom-linter.ts index 5de914e5f8f..eb8527b99d7 100644 --- a/packages/eslint-plugin-tslint/src/custom-linter.ts +++ b/packages/eslint-plugin-tslint/src/custom-linter.ts @@ -1,5 +1,5 @@ import { ILinterOptions, Linter, LintResult } from 'tslint'; -import { Program } from 'typescript'; +import { Program, SourceFile } from 'typescript'; // We need to access the program, but Linter has private program already // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -14,7 +14,7 @@ export class CustomLinter extends TSLintLinter { return super.getResult(); } - getSourceFile(fileName: string) { + getSourceFile(fileName: string): SourceFile | undefined { return this.program.getSourceFile(fileName); } } diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index a6db1f9ec46..516f9c48dae 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -124,65 +124,65 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e | Name | Description | :heavy_check_mark: | :wrench: | :thought_balloon: | | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | ----------------- | | [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive | :heavy_check_mark: | | | -| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | :heavy_check_mark: | :wrench: | | -| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | | | :thought_balloon: | -| [`@typescript-eslint/ban-ts-ignore`](./docs/rules/ban-ts-ignore.md) | Bans “// @ts-ignore” comments from being used | | | | -| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :heavy_check_mark: | :wrench: | | +| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | | :wrench: | | +| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :heavy_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/ban-ts-ignore`](./docs/rules/ban-ts-ignore.md) | Bans “// @ts-ignore” comments from being used | :heavy_check_mark: | | | +| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/camelcase`](./docs/rules/camelcase.md) | Enforce camelCase naming convention | :heavy_check_mark: | | | | [`@typescript-eslint/class-name-casing`](./docs/rules/class-name-casing.md) | Require PascalCased class and interface names | :heavy_check_mark: | | | | [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions. | :heavy_check_mark: | | | | [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | | | [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | :heavy_check_mark: | | | -| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | :heavy_check_mark: | | | +| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | | | | [`@typescript-eslint/func-call-spacing`](./docs/rules/func-call-spacing.md) | Require or disallow spacing between function identifiers and their invocations | | :wrench: | | | [`@typescript-eslint/generic-type-naming`](./docs/rules/generic-type-naming.md) | Enforces naming of generic type variables | | | | -| [`@typescript-eslint/indent`](./docs/rules/indent.md) | Enforce consistent indentation | :heavy_check_mark: | :wrench: | | -| [`@typescript-eslint/interface-name-prefix`](./docs/rules/interface-name-prefix.md) | Require that interface names be prefixed with `I` | :heavy_check_mark: | | | +| [`@typescript-eslint/indent`](./docs/rules/indent.md) | Enforce consistent indentation | | :wrench: | | +| [`@typescript-eslint/interface-name-prefix`](./docs/rules/interface-name-prefix.md) | Require that interface names should or should not prefixed with `I` | :heavy_check_mark: | | | | [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/member-naming`](./docs/rules/member-naming.md) | Enforces naming conventions for class members by visibility | | | | | [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | | | [`@typescript-eslint/no-array-constructor`](./docs/rules/no-array-constructor.md) | Disallow generic `Array` constructors | :heavy_check_mark: | :wrench: | | -| [`@typescript-eslint/no-empty-function`](./docs/rules/no-empty-function.md) | Disallow empty functions | | | | +| [`@typescript-eslint/no-empty-function`](./docs/rules/no-empty-function.md) | Disallow empty functions | :heavy_check_mark: | | | | [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :heavy_check_mark: | | | | [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-extra-parens`](./docs/rules/no-extra-parens.md) | Disallow unnecessary parentheses | | :wrench: | | | [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | | [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately. | | | :thought_balloon: | -| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | | | :thought_balloon: | +| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallows magic numbers | | | | | [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :heavy_check_mark: | | | -| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | | | :thought_balloon: | +| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :heavy_check_mark: | | | | [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :heavy_check_mark: | | | -| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | :heavy_check_mark: | | | +| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | | [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | -| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | | | | +| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :heavy_check_mark: | | | | [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | | [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: | | [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Warns if an explicitly specified type argument is the default for that type parameter | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :heavy_check_mark: | :wrench: | :thought_balloon: | | [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | | | [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | | | | [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | | | | [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :heavy_check_mark: | | | | [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | | | [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures | | :wrench: | | -| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | :heavy_check_mark: | :wrench: | :thought_balloon: | | [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/prefer-readonly`](./docs/rules/prefer-readonly.md) | Requires that private members are marked as `readonly` if they're never modified outside of the constructor | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Prefer RegExp#exec() over String#match() if no global flag is provided | | | :thought_balloon: | -| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Prefer RegExp#exec() over String#match() if no global flag is provided | :heavy_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | :heavy_check_mark: | :wrench: | :thought_balloon: | | [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | | :thought_balloon: | | [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Enforce giving `compare` argument to `Array#sort` | | | :thought_balloon: | -| [`@typescript-eslint/require-await`](./docs/rules/require-await.md) | Disallow async functions which have no `await` expression | | | :thought_balloon: | +| [`@typescript-eslint/require-await`](./docs/rules/require-await.md) | Disallow async functions which have no `await` expression | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | | | :thought_balloon: | | [`@typescript-eslint/semi`](./docs/rules/semi.md) | Require or disallow semicolons instead of ASI | | :wrench: | | | [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | | :thought_balloon: | -| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | | | | +| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :heavy_check_mark: | | | | [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/typedef`](./docs/rules/typedef.md) | Requires type annotations to exist | | | | -| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | | | :thought_balloon: | +| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | | diff --git a/packages/eslint-plugin/docs/rules/no-inferrable-types.md b/packages/eslint-plugin/docs/rules/no-inferrable-types.md index 9dbabe276c3..7dd159b02e5 100644 --- a/packages/eslint-plugin/docs/rules/no-inferrable-types.md +++ b/packages/eslint-plugin/docs/rules/no-inferrable-types.md @@ -24,8 +24,8 @@ The default options are: ```JSON { - "ignoreParameters": true, - "ignoreProperties": true, + "ignoreParameters": false, + "ignoreProperties": false, } ``` diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 516ee6b4f98..14b417ac5c7 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -49,8 +49,10 @@ "devDependencies": { "@types/json-schema": "^7.0.3", "@types/marked": "^0.6.5", + "@types/prettier": "^1.18.0", "chalk": "^2.4.2", "marked": "^0.7.0", + "prettier": "*", "typescript": "*" }, "peerDependencies": { diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json index 0c17ccb0426..30a7cafafb5 100644 --- a/packages/eslint-plugin/src/configs/all.json +++ b/packages/eslint-plugin/src/configs/all.json @@ -24,6 +24,7 @@ "@typescript-eslint/member-ordering": "error", "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", + "no-empty-function": "off", "@typescript-eslint/no-empty-function": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "error", @@ -62,6 +63,7 @@ "@typescript-eslint/prefer-string-starts-ends-with": "error", "@typescript-eslint/promise-function-async": "error", "@typescript-eslint/require-array-sort-compare": "error", + "require-await": "off", "@typescript-eslint/require-await": "error", "@typescript-eslint/restrict-plus-operands": "error", "semi": "off", diff --git a/packages/eslint-plugin/src/configs/base.json b/packages/eslint-plugin/src/configs/base.json index 6f56100a6ae..9580ed622cf 100644 --- a/packages/eslint-plugin/src/configs/base.json +++ b/packages/eslint-plugin/src/configs/base.json @@ -1,9 +1,5 @@ { "parser": "@typescript-eslint/parser", - "parserOptions": { - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint" - ] + "parserOptions": { "sourceType": "module" }, + "plugins": ["@typescript-eslint"] } diff --git a/packages/eslint-plugin/src/configs/recommended.json b/packages/eslint-plugin/src/configs/recommended.json index 121b85bf17a..95d18847686 100644 --- a/packages/eslint-plugin/src/configs/recommended.json +++ b/packages/eslint-plugin/src/configs/recommended.json @@ -1,38 +1,48 @@ { "extends": "./configs/base.json", "rules": { - "no-var": "error", - "prefer-const": "error", - "prefer-rest-params": "error", - "prefer-spread": "error", "@typescript-eslint/adjacent-overload-signatures": "error", - "@typescript-eslint/array-type": "error", + "@typescript-eslint/await-thenable": "error", + "@typescript-eslint/ban-ts-ignore": "error", "@typescript-eslint/ban-types": "error", "camelcase": "off", "@typescript-eslint/camelcase": "error", "@typescript-eslint/class-name-casing": "error", "@typescript-eslint/consistent-type-assertions": "error", "@typescript-eslint/explicit-function-return-type": "warn", - "@typescript-eslint/explicit-member-accessibility": "error", - "indent": "off", - "@typescript-eslint/indent": "error", "@typescript-eslint/interface-name-prefix": "error", "@typescript-eslint/member-delimiter-style": "error", "no-array-constructor": "off", "@typescript-eslint/no-array-constructor": "error", + "no-empty-function": "off", + "@typescript-eslint/no-empty-function": "error", "@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-misused-promises": "error", "@typescript-eslint/no-namespace": "error", - "@typescript-eslint/no-non-null-assertion": "error", - "@typescript-eslint/no-parameter-properties": "error", + "@typescript-eslint/no-non-null-assertion": "warn", + "@typescript-eslint/no-this-alias": "error", + "@typescript-eslint/no-unnecessary-type-assertion": "error", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "warn", "no-use-before-define": "off", "@typescript-eslint/no-use-before-define": "error", "@typescript-eslint/no-var-requires": "error", + "@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-namespace-keyword": "error", - "@typescript-eslint/type-annotation-spacing": "error" + "@typescript-eslint/prefer-regexp-exec": "error", + "@typescript-eslint/prefer-string-starts-ends-with": "error", + "require-await": "off", + "@typescript-eslint/require-await": "error", + "@typescript-eslint/triple-slash-reference": "error", + "@typescript-eslint/type-annotation-spacing": "error", + "@typescript-eslint/unbound-method": "error", + "no-var": "error", + "prefer-const": "error", + "prefer-rest-params": "error", + "prefer-spread": "error" } } diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index 8fe28bc3217..b9977618c40 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -94,7 +94,8 @@ export default util.createRule({ docs: { description: 'Requires using either `T[]` or `Array` for arrays', category: 'Stylistic Issues', - recommended: 'error', + // too opinionated to be recommended + recommended: false, }, fixable: 'code', messages: { @@ -168,7 +169,7 @@ export default util.createRule({ } return { - TSArrayType(node: TSESTree.TSArrayType) { + TSArrayType(node): void { if ( isArrayOption || (isArraySimpleOption && isSimpleType(node.elementType)) @@ -241,7 +242,7 @@ export default util.createRule({ }); }, - TSTypeReference(node: TSESTree.TSTypeReference) { + TSTypeReference(node): void { if ( isGenericOption || node.typeName.type !== AST_NODE_TYPES.Identifier diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 7a5db98db9c..304321001f7 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -9,7 +9,7 @@ export default util.createRule({ docs: { description: 'Disallows awaiting a value that is not a Thenable', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { await: 'Unexpected `await` of a non-Promise (non-"Thenable") value.', @@ -24,7 +24,7 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); return { - AwaitExpression(node) { + AwaitExpression(node): void { const originalNode = parserServices.esTreeNodeToTSNodeMap.get< ts.AwaitExpression >(node); diff --git a/packages/eslint-plugin/src/rules/ban-ts-ignore.ts b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts index 87af895627d..7d7a32e6cfc 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-ignore.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-ignore.ts @@ -7,7 +7,7 @@ export default util.createRule({ docs: { description: 'Bans “// @ts-ignore” comments from being used', category: 'Best Practices', - recommended: false, + recommended: 'error', }, schema: [], messages: { diff --git a/packages/eslint-plugin/src/rules/ban-types.ts b/packages/eslint-plugin/src/rules/ban-types.ts index bd3d8bf1b93..a8c2cec6c06 100644 --- a/packages/eslint-plugin/src/rules/ban-types.ts +++ b/packages/eslint-plugin/src/rules/ban-types.ts @@ -25,7 +25,7 @@ function stringifyTypeName( function getCustomMessage( bannedType: null | string | { message?: string; fixWith?: string }, -) { +): string { if (bannedType === null) { return ''; } @@ -108,7 +108,7 @@ export default util.createRule({ ], create(context, [{ types: bannedTypes }]) { return { - TSTypeReference({ typeName }) { + TSTypeReference({ typeName }): void { const name = stringifyTypeName(typeName, context.getSourceCode()); if (name in bannedTypes) { @@ -124,6 +124,7 @@ export default util.createRule({ name: name, customMessage, }, + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type fix: fixWith ? fixer => fixer.replaceText(typeName, fixWith) : null, }); } diff --git a/packages/eslint-plugin/src/rules/camelcase.ts b/packages/eslint-plugin/src/rules/camelcase.ts index ffa5a62ed89..4bb614cba9d 100644 --- a/packages/eslint-plugin/src/rules/camelcase.ts +++ b/packages/eslint-plugin/src/rules/camelcase.ts @@ -90,7 +90,7 @@ export default util.createRule({ } return { - Identifier(node) { + Identifier(node): void { /* * Leading and trailing underscores are commonly used to flag * private/protected identifiers, strip them diff --git a/packages/eslint-plugin/src/rules/class-name-casing.ts b/packages/eslint-plugin/src/rules/class-name-casing.ts index 1c76edd118b..cb238f87ac7 100644 --- a/packages/eslint-plugin/src/rules/class-name-casing.ts +++ b/packages/eslint-plugin/src/rules/class-name-casing.ts @@ -64,7 +64,7 @@ export default util.createRule({ | TSESTree.ClassDeclaration | TSESTree.TSInterfaceDeclaration | TSESTree.ClassExpression, - ) { + ): void { // class expressions (i.e. export default class {}) are OK if (node.id && !isPascalCase(node.id.name)) { report(node, node.id); @@ -72,7 +72,7 @@ export default util.createRule({ }, "VariableDeclarator[init.type='ClassExpression']"( node: TSESTree.VariableDeclarator, - ) { + ): void { if ( node.id.type === AST_NODE_TYPES.ArrayPattern || node.id.type === AST_NODE_TYPES.ObjectPattern diff --git a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts index 6380f9f0003..a5f87250da0 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts @@ -77,7 +77,7 @@ export default util.createRule({ function reportIncorrectAssertionType( node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression, - ) { + ): void { const messageId = options.assertionStyle; context.report({ node, @@ -89,7 +89,7 @@ export default util.createRule({ }); } - function checkType(node: TSESTree.TypeNode) { + function checkType(node: TSESTree.TypeNode): boolean { switch (node.type) { case AST_NODE_TYPES.TSAnyKeyword: case AST_NODE_TYPES.TSUnknownKeyword: @@ -107,7 +107,7 @@ export default util.createRule({ function checkExpression( node: TSESTree.TSTypeAssertion | TSESTree.TSAsExpression, - ) { + ): void { if ( options.assertionStyle === 'never' || options.objectLiteralTypeAssertions === 'allow' || @@ -137,7 +137,7 @@ export default util.createRule({ } return { - TSTypeAssertion(node) { + TSTypeAssertion(node): void { if (options.assertionStyle !== 'angle-bracket') { reportIncorrectAssertionType(node); return; @@ -145,7 +145,7 @@ export default util.createRule({ checkExpression(node); }, - TSAsExpression(node) { + TSAsExpression(node): void { if (options.assertionStyle !== 'as') { reportIncorrectAssertionType(node); return; diff --git a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts index 01fa92dd3d0..cf9e851c81c 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts @@ -9,6 +9,7 @@ export default util.createRule({ description: 'Consistent with type definition either `interface` or `type`', category: 'Stylistic Issues', + // too opinionated to be recommended recommended: false, }, messages: { @@ -29,7 +30,7 @@ export default util.createRule({ return { "TSTypeAliasDeclaration[typeAnnotation.type='TSTypeLiteral']"( node: TSESTree.TSTypeAliasDeclaration, - ) { + ): void { if (option === 'interface') { context.report({ node: node.id, @@ -63,7 +64,7 @@ export default util.createRule({ }); } }, - TSInterfaceDeclaration(node) { + TSInterfaceDeclaration(node): void { if (option === 'type') { context.report({ node: node.id, diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index 44ea2d03c8e..67692c20fc0 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -47,8 +47,8 @@ export default util.createRule({ defaultOptions: [ { allowExpressions: false, - allowTypedFunctionExpressions: false, - allowHigherOrderFunctions: false, + allowTypedFunctionExpressions: true, + allowHigherOrderFunctions: true, }, ], create(context, [options]) { diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index 8d2b590ffad..21a5a8cda18 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -33,8 +33,9 @@ export default util.createRule({ docs: { description: 'Require explicit accessibility modifiers on class properties and methods', - category: 'Best Practices', - recommended: 'error', + category: 'Stylistic Issues', + // too opinionated to be recommended + recommended: false, }, messages: { missingAccessibility: @@ -82,7 +83,7 @@ export default util.createRule({ nodeType: string, node: TSESTree.Node, nodeName: string, - ) { + ): void { context.report({ node: node, messageId: messageId, @@ -179,7 +180,7 @@ export default util.createRule({ */ function checkParameterPropertyAccessibilityModifier( node: TSESTree.TSParameterProperty, - ) { + ): void { const nodeType = 'parameter property'; // HAS to be an identifier or assignment or TSC will throw if ( diff --git a/packages/eslint-plugin/src/rules/generic-type-naming.ts b/packages/eslint-plugin/src/rules/generic-type-naming.ts index 784a2fc3b0c..95516174448 100644 --- a/packages/eslint-plugin/src/rules/generic-type-naming.ts +++ b/packages/eslint-plugin/src/rules/generic-type-naming.ts @@ -10,6 +10,7 @@ export default util.createRule({ docs: { description: 'Enforces naming of generic type variables', category: 'Stylistic Issues', + // too opinionated to be recommended recommended: false, }, messages: { @@ -30,7 +31,7 @@ export default util.createRule({ const regex = new RegExp(rule!); return { - TSTypeParameter(node) { + TSTypeParameter(node): void { const name = node.name.name; if (name && !regex.test(name)) { diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts index 475e3c35d7b..082ca05129d 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/OffsetStorage.ts @@ -2,7 +2,11 @@ // License: https://github.com/eslint/eslint/blob/48700fc8408f394887cdedd071b22b757700fdcb/LICENSE import { TSESTree } from '@typescript-eslint/experimental-utils'; -import { BinarySearchTree, TokenOrComment } from './BinarySearchTree'; +import { + BinarySearchTree, + TokenOrComment, + TreeValue, +} from './BinarySearchTree'; import { TokenInfo } from './TokenInfo'; /** @@ -34,7 +38,7 @@ export class OffsetStorage { this.ignoredTokens = new WeakSet(); } - private getOffsetDescriptor(token: TokenOrComment) { + private getOffsetDescriptor(token: TokenOrComment): TreeValue { return this.tree.findLe(token.range[0]).value; } @@ -151,8 +155,8 @@ export class OffsetStorage { public setDesiredOffsets( range: [number, number], fromToken: TokenOrComment | null, - offset: number = 0, - force: boolean = false, + offset = 0, + force = false, ): void { /* * Offset ranges are stored as a collection of nodes, where each node maps a numeric key to an offset diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts index 3549da45d74..56909f15fa7 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts @@ -25,15 +25,13 @@ import { OffsetStorage } from './OffsetStorage'; import { TokenInfo } from './TokenInfo'; import { createRule, ExcludeKeys, RequireKeys } from '../../util'; -function createGlobalLinebreakMatcher() { - return /\r\n|[\r\n\u2028\u2029]/gu; -} +const GLOBAL_LINEBREAK_REGEX = /\r\n|[\r\n\u2028\u2029]/gu; +const WHITESPACE_REGEX = /\s*$/u; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -const WHITESPACE_REGEX = /\s*$/u; const KNOWN_NODES = new Set([ AST_NODE_TYPES.AssignmentExpression, AST_NODE_TYPES.AssignmentPattern, @@ -440,7 +438,7 @@ export default createRule({ expectedAmount: number, actualSpaces: number, actualTabs: number, - ) { + ): { expected: string; actual: string | number } { const expectedStatement = `${expectedAmount} ${indentType}${ expectedAmount === 1 ? '' : 's' }`; // e.g. "2 tabs" @@ -568,9 +566,7 @@ export default createRule({ */ function countTrailingLinebreaks(str: string): number { const trailingWhitespace = WHITESPACE_REGEX.exec(str)![0]; - const linebreakMatches = createGlobalLinebreakMatcher().exec( - trailingWhitespace, - ); + const linebreakMatches = GLOBAL_LINEBREAK_REGEX.exec(trailingWhitespace); return linebreakMatches === null ? 0 : linebreakMatches.length; } @@ -587,7 +583,7 @@ export default createRule({ startToken: TSESTree.Token, endToken: TSESTree.Token, offset: number | string, - ) { + ): void { /** * Gets the first token of a given element, including surrounding parentheses. * @param element A node in the `elements` list @@ -1589,6 +1585,7 @@ export default createRule({ const listener = baseOffsetListeners[key] as TSESLint.RuleFunction< TSESTree.Node >; + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type acc[key] = node => listenerCallQueue.push({ listener, node }); return acc; diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index 76d1edf1cdb..aca492d4b4d 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -90,7 +90,8 @@ export default util.createRule({ docs: { description: 'Enforce consistent indentation', category: 'Stylistic Issues', - recommended: 'error', + // too opinionated to be recommended + recommended: false, }, fixable: 'whitespace', schema: baseRule.meta.schema, diff --git a/packages/eslint-plugin/src/rules/interface-name-prefix.ts b/packages/eslint-plugin/src/rules/interface-name-prefix.ts index 1af78f79a53..11976552221 100644 --- a/packages/eslint-plugin/src/rules/interface-name-prefix.ts +++ b/packages/eslint-plugin/src/rules/interface-name-prefix.ts @@ -8,8 +8,11 @@ export default util.createRule({ meta: { type: 'suggestion', docs: { - description: 'Require that interface names be prefixed with `I`', + description: + 'Require that interface names should or should not prefixed with `I`', category: 'Stylistic Issues', + // this will always be recommended as there's no reason to use this convention + // https://github.com/typescript-eslint/typescript-eslint/issues/374 recommended: 'error', }, messages: { diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index d2becd1655f..72020afc600 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -364,28 +364,28 @@ export default util.createRule({ } return { - ClassDeclaration(node) { + ClassDeclaration(node): void { validateMembersOrder( node.body.body, options.classes || options.default!, true, ); }, - ClassExpression(node) { + ClassExpression(node): void { validateMembersOrder( node.body.body, options.classExpressions || options.default!, true, ); }, - TSInterfaceDeclaration(node) { + TSInterfaceDeclaration(node): void { validateMembersOrder( node.body.body, options.interfaces || options.default!, false, ); }, - TSTypeLiteral(node) { + TSTypeLiteral(node): void { validateMembersOrder( node.members, options.typeLiterals || options.default!, diff --git a/packages/eslint-plugin/src/rules/no-empty-function.ts b/packages/eslint-plugin/src/rules/no-empty-function.ts index d64568a874f..31aa5d8bb63 100644 --- a/packages/eslint-plugin/src/rules/no-empty-function.ts +++ b/packages/eslint-plugin/src/rules/no-empty-function.ts @@ -15,7 +15,7 @@ export default util.createRule({ docs: { description: 'Disallow empty functions', category: 'Best Practices', - recommended: false, + recommended: 'error', }, schema: baseRule.meta.schema, messages: baseRule.meta.messages, @@ -81,7 +81,7 @@ export default util.createRule({ */ function isConciseConstructor( node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression, - ) { + ): boolean { // Check TypeScript specific nodes return ( isConstructor(node) && isBodyEmpty(node) && hasParameterProperties(node) @@ -89,12 +89,12 @@ export default util.createRule({ } return { - FunctionDeclaration(node: TSESTree.FunctionDeclaration) { + FunctionDeclaration(node): void { if (!isConciseConstructor(node)) { rules.FunctionDeclaration(node); } }, - FunctionExpression(node: TSESTree.FunctionExpression) { + FunctionExpression(node): void { if (!isConciseConstructor(node)) { rules.FunctionExpression(node); } diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 4d2a0a5a488..55fbdb5337e 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -40,7 +40,7 @@ export default util.createRule({ ], create(context, [{ allowSingleExtends }]) { return { - TSInterfaceDeclaration(node) { + TSInterfaceDeclaration(node): void { if (node.body.body.length !== 0) { // interface contains members --> Nothing to report return; diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 43f81b8607e..249265a7683 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -167,7 +167,7 @@ export default util.createRule({ } return { - TSAnyKeyword(node) { + TSAnyKeyword(node): void { if (ignoreRestArgs && isNodeDescendantOfRestElementInFunction(node)) { return; } @@ -175,7 +175,8 @@ export default util.createRule({ let fix: TSESLint.ReportFixFunction | null = null; if (fixToUnknown) { - fix = fixer => fixer.replaceText(node, 'unknown'); + fix = (fixer => + fixer.replaceText(node, 'unknown')) as TSESLint.ReportFixFunction; } context.report({ diff --git a/packages/eslint-plugin/src/rules/no-extra-parens.ts b/packages/eslint-plugin/src/rules/no-extra-parens.ts index 28e69478d7e..7b8d091807c 100644 --- a/packages/eslint-plugin/src/rules/no-extra-parens.ts +++ b/packages/eslint-plugin/src/rules/no-extra-parens.ts @@ -31,7 +31,7 @@ export default util.createRule({ function binaryExp( node: TSESTree.BinaryExpression | TSESTree.LogicalExpression, - ) { + ): void { const rule = rules.BinaryExpression as (n: typeof node) => void; // makes the rule think it should skip the left or right @@ -56,7 +56,9 @@ export default util.createRule({ return rule(node); } - function callExp(node: TSESTree.CallExpression | TSESTree.NewExpression) { + function callExp( + node: TSESTree.CallExpression | TSESTree.NewExpression, + ): void { const rule = rules.CallExpression as (n: typeof node) => void; if (node.callee.type === AST_NODE_TYPES.TSAsExpression) { @@ -74,7 +76,7 @@ export default util.createRule({ } function unaryUpdateExpression( node: TSESTree.UnaryExpression | TSESTree.UpdateExpression, - ) { + ): void { const rule = rules.UnaryExpression as (n: typeof node) => void; if (node.argument.type === AST_NODE_TYPES.TSAsExpression) { diff --git a/packages/eslint-plugin/src/rules/no-extraneous-class.ts b/packages/eslint-plugin/src/rules/no-extraneous-class.ts index 846416866f2..4756b5928f3 100644 --- a/packages/eslint-plugin/src/rules/no-extraneous-class.ts +++ b/packages/eslint-plugin/src/rules/no-extraneous-class.ts @@ -54,7 +54,7 @@ export default util.createRule({ ], create(context, [{ allowConstructorOnly, allowEmpty, allowStaticOnly }]) { return { - ClassBody(node) { + ClassBody(node): void { const parent = node.parent as | TSESTree.ClassDeclaration | TSESTree.ClassExpression diff --git a/packages/eslint-plugin/src/rules/no-floating-promises.ts b/packages/eslint-plugin/src/rules/no-floating-promises.ts index 04d6664525c..5bc2f75adaa 100644 --- a/packages/eslint-plugin/src/rules/no-floating-promises.ts +++ b/packages/eslint-plugin/src/rules/no-floating-promises.ts @@ -24,7 +24,7 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); return { - ExpressionStatement(node) { + ExpressionStatement(node): void { const { expression } = parserServices.esTreeNodeToTSNodeMap.get< ts.ExpressionStatement >(node); diff --git a/packages/eslint-plugin/src/rules/no-for-in-array.ts b/packages/eslint-plugin/src/rules/no-for-in-array.ts index 970c621887e..03171e7fdf7 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -7,7 +7,7 @@ export default util.createRule({ docs: { description: 'Disallow iterating over an array with a for-in loop', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { forInViolation: @@ -19,7 +19,7 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - ForInStatement(node) { + ForInStatement(node): void { const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); const originalNode = parserServices.esTreeNodeToTSNodeMap.get< diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index f3b44e512fa..40fc6a60c7e 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -44,24 +44,30 @@ export default util.createRule({ }, defaultOptions: [ { - ignoreParameters: true, - ignoreProperties: true, + ignoreParameters: false, + ignoreProperties: false, }, ], create(context, [{ ignoreParameters, ignoreProperties }]) { - function isFunctionCall(init: TSESTree.Expression, callName: string) { + function isFunctionCall( + init: TSESTree.Expression, + callName: string, + ): boolean { return ( init.type === AST_NODE_TYPES.CallExpression && init.callee.type === AST_NODE_TYPES.Identifier && init.callee.name === callName ); } - function isLiteral(init: TSESTree.Expression, typeName: string) { + function isLiteral(init: TSESTree.Expression, typeName: string): boolean { return ( init.type === AST_NODE_TYPES.Literal && typeof init.value === typeName ); } - function isIdentifier(init: TSESTree.Expression, ...names: string[]) { + function isIdentifier( + init: TSESTree.Expression, + ...names: string[] + ): boolean { return ( init.type === AST_NODE_TYPES.Identifier && names.includes(init.name) ); diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 8a50fa87c39..005bae9eb0a 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -150,7 +150,7 @@ export default util.createRule({ } return { - Literal(node) { + Literal(node): void { // Check if the node is a TypeScript enum declaration if (options.ignoreEnums && isParentTSEnumDeclaration(node)) { return; diff --git a/packages/eslint-plugin/src/rules/no-misused-new.ts b/packages/eslint-plugin/src/rules/no-misused-new.ts index aa9d0cb366c..67d00b131f0 100644 --- a/packages/eslint-plugin/src/rules/no-misused-new.ts +++ b/packages/eslint-plugin/src/rules/no-misused-new.ts @@ -16,7 +16,7 @@ export default util.createRule({ schema: [], messages: { errorMessageInterface: 'Interfaces cannot be constructed, only classes.', - errorMessageClass: 'Class cannon have method named `new`.', + errorMessageClass: 'Class cannot have method named `new`.', }, }, defaultOptions: [], @@ -69,7 +69,7 @@ export default util.createRule({ return { 'TSInterfaceBody > TSConstructSignatureDeclaration'( node: TSESTree.TSConstructSignatureDeclaration, - ) { + ): void { if ( isMatchingParentType( node.parent!.parent as TSESTree.TSInterfaceDeclaration, @@ -85,7 +85,7 @@ export default util.createRule({ }, "TSMethodSignature[key.name='constructor']"( node: TSESTree.TSMethodSignature, - ) { + ): void { context.report({ node, messageId: 'errorMessageInterface', @@ -93,7 +93,7 @@ export default util.createRule({ }, "ClassBody > MethodDefinition[key.name='new']"( node: TSESTree.MethodDefinition, - ) { + ): void { if (node.value.type === AST_NODE_TYPES.TSEmptyBodyFunctionExpression) { if ( node.parent && diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index b36046352d7..6d06ef8807a 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -17,7 +17,7 @@ export default util.createRule({ docs: { description: 'Avoid using promises in places not designed to handle them', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { voidReturn: @@ -73,13 +73,15 @@ export default util.createRule({ NewExpression: checkArguments, }; - function checkTestConditional(node: { test: TSESTree.Expression | null }) { + function checkTestConditional(node: { + test: TSESTree.Expression | null; + }): void { if (node.test) { checkConditional(node.test); } } - function checkConditional(node: TSESTree.Expression) { + function checkConditional(node: TSESTree.Expression): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); if (isAlwaysThenable(checker, tsNode)) { context.report({ @@ -91,7 +93,7 @@ export default util.createRule({ function checkArguments( node: TSESTree.CallExpression | TSESTree.NewExpression, - ) { + ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get< ts.CallExpression | ts.NewExpression >(node); @@ -126,7 +128,7 @@ export default util.createRule({ // alternates in a union) to be thenable. Otherwise, you might be trying to // check if something is defined or undefined and get caught because one of the // branches is thenable. -function isAlwaysThenable(checker: ts.TypeChecker, node: ts.Node) { +function isAlwaysThenable(checker: ts.TypeChecker, node: ts.Node): boolean { const type = checker.getTypeAtLocation(node); for (const subType of tsutils.unionTypeParts(checker.getApparentType(type))) { @@ -195,7 +197,7 @@ function isFunctionParam( function voidFunctionParams( checker: ts.TypeChecker, node: ts.CallExpression | ts.NewExpression, -) { +): Set { const voidReturnIndices = new Set(); const thenableReturnIndices = new Set(); const type = checker.getTypeAtLocation(node.expression); @@ -237,7 +239,10 @@ function voidFunctionParams( } // Returns true if the expression is a function that returns a thenable -function returnsThenable(checker: ts.TypeChecker, node: ts.Expression) { +function returnsThenable( + checker: ts.TypeChecker, + node: ts.Expression, +): boolean { const type = checker.getApparentType(checker.getTypeAtLocation(node)); for (const subType of tsutils.unionTypeParts(type)) { diff --git a/packages/eslint-plugin/src/rules/no-namespace.ts b/packages/eslint-plugin/src/rules/no-namespace.ts index ca68fcf647b..3698b4f941b 100644 --- a/packages/eslint-plugin/src/rules/no-namespace.ts +++ b/packages/eslint-plugin/src/rules/no-namespace.ts @@ -53,7 +53,7 @@ export default util.createRule({ return { "TSModuleDeclaration[global!=true][id.type='Identifier']"( node: TSESTree.TSModuleDeclaration, - ) { + ): void { if ( (node.parent && node.parent.type === AST_NODE_TYPES.TSModuleDeclaration) || diff --git a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts index 6ed336e4d2d..4e888c58bb6 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts @@ -8,7 +8,7 @@ export default util.createRule({ description: 'Disallows non-null assertions using the `!` postfix operator', category: 'Stylistic Issues', - recommended: 'error', + recommended: 'warn', }, messages: { noNonNull: 'Forbidden non-null assertion.', @@ -18,7 +18,7 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - TSNonNullExpression(node) { + TSNonNullExpression(node): void { context.report({ node, messageId: 'noNonNull', diff --git a/packages/eslint-plugin/src/rules/no-parameter-properties.ts b/packages/eslint-plugin/src/rules/no-parameter-properties.ts index a7727a33602..9b6bb31e654 100644 --- a/packages/eslint-plugin/src/rules/no-parameter-properties.ts +++ b/packages/eslint-plugin/src/rules/no-parameter-properties.ts @@ -27,7 +27,8 @@ export default util.createRule({ description: 'Disallow the use of parameter properties in class constructors', category: 'Stylistic Issues', - recommended: 'error', + // too opinionated to be recommended + recommended: false, }, messages: { noParamProp: @@ -81,7 +82,7 @@ export default util.createRule({ } return { - TSParameterProperty(node) { + TSParameterProperty(node): void { const modifiers = getModifiers(node); if (!allows.includes(modifiers)) { diff --git a/packages/eslint-plugin/src/rules/no-require-imports.ts b/packages/eslint-plugin/src/rules/no-require-imports.ts index afb0b4a3848..91d81e0d8c5 100644 --- a/packages/eslint-plugin/src/rules/no-require-imports.ts +++ b/packages/eslint-plugin/src/rules/no-require-imports.ts @@ -18,13 +18,15 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - 'CallExpression > Identifier[name="require"]'(node: TSESTree.Identifier) { + 'CallExpression > Identifier[name="require"]'( + node: TSESTree.Identifier, + ): void { context.report({ node: node.parent!, messageId: 'noRequireImports', }); }, - TSExternalModuleReference(node) { + TSExternalModuleReference(node): void { context.report({ node, messageId: 'noRequireImports', diff --git a/packages/eslint-plugin/src/rules/no-this-alias.ts b/packages/eslint-plugin/src/rules/no-this-alias.ts index e156cbd24e2..8865fad2c3f 100644 --- a/packages/eslint-plugin/src/rules/no-this-alias.ts +++ b/packages/eslint-plugin/src/rules/no-this-alias.ts @@ -19,7 +19,7 @@ export default util.createRule({ docs: { description: 'Disallow aliasing `this`', category: 'Best Practices', - recommended: false, + recommended: 'error', }, schema: [ { @@ -46,7 +46,7 @@ export default util.createRule({ }, defaultOptions: [ { - allowDestructuring: false, + allowDestructuring: true, allowedNames: [], }, ], @@ -54,7 +54,7 @@ export default util.createRule({ return { "VariableDeclarator[init.type='ThisExpression']"( node: TSESTree.VariableDeclarator, - ) { + ): void { const { id } = node; if (allowDestructuring && id.type !== AST_NODE_TYPES.Identifier) { diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index f260d124133..1648b89f0df 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -44,6 +44,7 @@ export default util.createRule({ docs: { description: 'Disallow the use of type aliases', category: 'Stylistic Issues', + // too opinionated to be recommended recommended: false, }, messages: { @@ -188,7 +189,7 @@ export default util.createRule({ */ function validateTypeAliases( type: TypeWithLabel, - isTopLevel: boolean = false, + isTopLevel = false, ): void { if (type.node.type === AST_NODE_TYPES.TSFunctionType) { // callback @@ -268,7 +269,7 @@ export default util.createRule({ } return { - TSTypeAliasDeclaration(node) { + TSTypeAliasDeclaration(node): void { const types = getTypes(node.typeAnnotation); if (types.length === 1) { // is a top level type annotation diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index 23a98cb9bef..64f58848d79 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -132,7 +132,7 @@ export default util.createRule({ namespacesInScope.push(esTreeNodeToTSNodeMap.get(node)); } - function exitDeclaration() { + function exitDeclaration(): void { namespacesInScope.pop(); } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index d93e205c7bb..100a9d261c0 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -73,7 +73,7 @@ export default util.createRule<[], MessageIds>({ } return { - TSTypeParameterInstantiation(node) { + TSTypeParameterInstantiation(node): void { const parentDeclaration = parserServices.esTreeNodeToTSNodeMap.get< ExtendingClassLikeDeclaration | ParameterCapableTSNode >(node.parent!); @@ -104,7 +104,7 @@ function getArgsAndParameters( function getTypeParametersFromNode( node: ParameterCapableTSNode, checker: ts.TypeChecker, -) { +): readonly ts.TypeParameterDeclaration[] | undefined { if (ts.isExpressionWithTypeArguments(node)) { return getTypeParametersFromType(node.expression, checker); } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index c91c3d678c7..11da74d88c9 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -27,7 +27,7 @@ export default util.createRule({ description: 'Warns if a type assertion does not change the type of an expression', category: 'Best Practices', - recommended: false, + recommended: 'error', }, fixable: 'code', messages: { @@ -166,7 +166,7 @@ export default util.createRule({ } return { - TSNonNullExpression(node) { + TSNonNullExpression(node): void { const originalNode = parserServices.esTreeNodeToTSNodeMap.get< ts.NonNullExpression >(node); diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index 20ed4edc77a..e40da703893 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -255,7 +255,7 @@ export default util.createRule({ } return { - Program() { + Program(): void { findVariablesInScope(context.getScope()); }, }; diff --git a/packages/eslint-plugin/src/rules/no-useless-constructor.ts b/packages/eslint-plugin/src/rules/no-useless-constructor.ts index 6410fa5fa43..3587c795311 100644 --- a/packages/eslint-plugin/src/rules/no-useless-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-useless-constructor.ts @@ -59,7 +59,7 @@ export default util.createRule({ create(context) { const rules = baseRule.create(context); return { - MethodDefinition(node) { + MethodDefinition(node): void { if ( node.value && node.value.type === AST_NODE_TYPES.FunctionExpression && diff --git a/packages/eslint-plugin/src/rules/no-var-requires.ts b/packages/eslint-plugin/src/rules/no-var-requires.ts index 29b1c77dd34..274cf2c1ceb 100644 --- a/packages/eslint-plugin/src/rules/no-var-requires.ts +++ b/packages/eslint-plugin/src/rules/no-var-requires.ts @@ -22,7 +22,7 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - CallExpression(node) { + CallExpression(node): void { if ( node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === 'require' && diff --git a/packages/eslint-plugin/src/rules/prefer-for-of.ts b/packages/eslint-plugin/src/rules/prefer-for-of.ts index 89f6c540303..5aef0845a53 100644 --- a/packages/eslint-plugin/src/rules/prefer-for-of.ts +++ b/packages/eslint-plugin/src/rules/prefer-for-of.ts @@ -181,7 +181,7 @@ export default util.createRule({ } return { - 'ForStatement:exit'(node: TSESTree.ForStatement) { + 'ForStatement:exit'(node: TSESTree.ForStatement): void { if (!isSingleVariableDeclaration(node.init)) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-function-type.ts b/packages/eslint-plugin/src/rules/prefer-function-type.ts index f375b1bb8f2..dae4fae3295 100644 --- a/packages/eslint-plugin/src/rules/prefer-function-type.ts +++ b/packages/eslint-plugin/src/rules/prefer-function-type.ts @@ -72,7 +72,7 @@ export default util.createRule({ | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructSignatureDeclaration, parent: TSESTree.Node, - ) { + ): string { const start = call.range[0]; const colonPos = call.returnType!.range[0] - start; const text = sourceCode.getText().slice(start, call.range[1]); @@ -102,7 +102,10 @@ export default util.createRule({ * @param member The TypeElement being checked * @param node The parent of member being checked */ - function checkMember(member: TSESTree.TypeElement, node: TSESTree.Node) { + function checkMember( + member: TSESTree.TypeElement, + node: TSESTree.Node, + ): void { if ( (member.type === AST_NODE_TYPES.TSCallSignatureDeclaration || member.type === AST_NODE_TYPES.TSConstructSignatureDeclaration) && @@ -141,12 +144,12 @@ export default util.createRule({ } return { - TSInterfaceDeclaration(node) { + TSInterfaceDeclaration(node): void { if (!hasOneSupertype(node) && node.body.body.length === 1) { checkMember(node.body.body[0], node); } }, - 'TSTypeLiteral[members.length = 1]'(node: TSESTree.TSTypeLiteral) { + 'TSTypeLiteral[members.length = 1]'(node: TSESTree.TSTypeLiteral): void { checkMember(node.members[0], node); }, }; diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 2db17e11d1d..384edf01859 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -13,7 +13,7 @@ export default createRule({ docs: { description: 'Enforce `includes` method over `indexOf` method', category: 'Best Practices', - recommended: false, + recommended: 'error', }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts index 6059a731a94..9137fe912aa 100644 --- a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts +++ b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts @@ -26,7 +26,7 @@ export default util.createRule({ const sourceCode = context.getSourceCode(); return { - TSModuleDeclaration(node) { + TSModuleDeclaration(node): void { // Do nothing if the name is a string. if (!node.id || node.id.type === AST_NODE_TYPES.Literal) { return; diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 01f4ea320ba..22c85fd0343 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -61,7 +61,7 @@ export default util.createRule({ node: ts.PropertyAccessExpression, parent: ts.Node, classScope: ClassScope, - ) { + ): void { if (ts.isBinaryExpression(parent)) { handleParentBinaryExpression(node, parent, classScope); return; @@ -84,7 +84,7 @@ export default util.createRule({ node: ts.PropertyAccessExpression, parent: ts.BinaryExpression, classScope: ClassScope, - ) { + ): void { if ( parent.left === node && tsutils.isAssignmentKind(parent.operatorToken.kind) @@ -96,7 +96,7 @@ export default util.createRule({ function handleParentPostfixOrPrefixUnaryExpression( node: ts.PostfixUnaryExpression | ts.PrefixUnaryExpression, classScope: ClassScope, - ) { + ): void { if ( node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken @@ -107,14 +107,16 @@ export default util.createRule({ } } - function isConstructor(node: TSESTree.Node) { + function isConstructor(node: TSESTree.Node): boolean { return ( node.type === AST_NODE_TYPES.MethodDefinition && node.kind === 'constructor' ); } - function isFunctionScopeBoundaryInStack(node: TSESTree.Node) { + function isFunctionScopeBoundaryInStack( + node: TSESTree.Node, + ): boolean | tsutils.ScopeBoundary { if (classScopeStack.length === 0) { return false; } @@ -129,7 +131,7 @@ export default util.createRule({ function getEsNodesFromViolatingNode( violatingNode: ParameterOrPropertyDeclaration, - ) { + ): { esNode: TSESTree.Node; nameNode: TSESTree.Node } { if (ts.isParameterPropertyDeclaration(violatingNode)) { return { esNode: parserServices.tsNodeToESTreeNodeMap.get(violatingNode.name), @@ -148,7 +150,7 @@ export default util.createRule({ return { 'ClassDeclaration, ClassExpression'( node: TSESTree.ClassDeclaration | TSESTree.ClassExpression, - ) { + ): void { classScopeStack.push( new ClassScope( checker, @@ -157,7 +159,7 @@ export default util.createRule({ ), ); }, - 'ClassDeclaration, ClassExpression:exit'() { + 'ClassDeclaration, ClassExpression:exit'(): void { const finalizedClassScope = classScopeStack.pop()!; const sourceCode = context.getSourceCode(); @@ -175,7 +177,7 @@ export default util.createRule({ }); } }, - MemberExpression(node) { + MemberExpression(node): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get< ts.PropertyAccessExpression >(node); @@ -187,7 +189,7 @@ export default util.createRule({ ); } }, - [functionScopeBoundaries](node: TSESTree.Node) { + [functionScopeBoundaries](node: TSESTree.Node): void { if (isConstructor(node)) { classScopeStack[classScopeStack.length - 1].enterConstructor( parserServices.esTreeNodeToTSNodeMap.get( @@ -198,7 +200,7 @@ export default util.createRule({ classScopeStack[classScopeStack.length - 1].enterNonConstructor(); } }, - [`${functionScopeBoundaries}:exit`](node: TSESTree.Node) { + [`${functionScopeBoundaries}:exit`](node: TSESTree.Node): void { if (isConstructor(node)) { classScopeStack[classScopeStack.length - 1].exitConstructor(); } else if (isFunctionScopeBoundaryInStack(node)) { @@ -247,7 +249,7 @@ class ClassScope { } } - public addDeclaredVariable(node: ParameterOrPropertyDeclaration) { + public addDeclaredVariable(node: ParameterOrPropertyDeclaration): void { if ( !tsutils.isModifierFlagSet(node, ts.ModifierFlags.Private) || tsutils.isModifierFlagSet(node, ts.ModifierFlags.Readonly) || @@ -270,7 +272,7 @@ class ClassScope { ).set(node.name.getText(), node); } - public addVariableModification(node: ts.PropertyAccessExpression) { + public addVariableModification(node: ts.PropertyAccessExpression): void { const modifierType = this.checker.getTypeAtLocation(node.expression); if ( modifierType.symbol === undefined || @@ -295,7 +297,7 @@ class ClassScope { ).add(node.name.text); } - public enterConstructor(node: ts.ConstructorDeclaration) { + public enterConstructor(node: ts.ConstructorDeclaration): void { this.constructorScopeDepth = DIRECTLY_INSIDE_CONSTRUCTOR; for (const parameter of node.parameters) { @@ -305,23 +307,23 @@ class ClassScope { } } - public exitConstructor() { + public exitConstructor(): void { this.constructorScopeDepth = OUTSIDE_CONSTRUCTOR; } - public enterNonConstructor() { + public enterNonConstructor(): void { if (this.constructorScopeDepth !== OUTSIDE_CONSTRUCTOR) { this.constructorScopeDepth += 1; } } - public exitNonConstructor() { + public exitNonConstructor(): void { if (this.constructorScopeDepth !== OUTSIDE_CONSTRUCTOR) { this.constructorScopeDepth -= 1; } } - public finalizeUnmodifiedPrivateNonReadonlys() { + public finalizeUnmodifiedPrivateNonReadonlys(): ParameterOrPropertyDeclaration[] { this.memberVariableModifications.forEach(variableName => { this.privateModifiableMembers.delete(variableName); }); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index c48e2351985..bd1a48fcb61 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -12,7 +12,7 @@ export default createRule({ description: 'Prefer RegExp#exec() over String#match() if no global flag is provided', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { regExpExecOverStringMatch: 'Use the `RegExp#exec()` method instead.', @@ -39,7 +39,7 @@ export default createRule({ return { "CallExpression[arguments.length=1] > MemberExpression.callee[property.name='match'][computed=false]"( node: TSESTree.MemberExpression, - ) { + ): void { const callNode = node.parent as TSESTree.CallExpression; const arg = callNode.arguments[0]; const evaluated = getStaticValue(arg, globalScope); diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index 4e902dfd584..2ffac6728ac 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -20,7 +20,7 @@ export default createRule({ description: 'Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { preferStartsWith: "Use 'String#startsWith' method instead.", diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 48d63cf0f54..faf55f95fa7 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -86,7 +86,7 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); - function validateNode(node: TSESTree.Node) { + function validateNode(node: TSESTree.Node): void { const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); const signatures = checker .getTypeAtLocation(originalNode) @@ -111,17 +111,21 @@ export default util.createRule({ return { 'ArrowFunctionExpression[async = false]'( node: TSESTree.ArrowFunctionExpression, - ) { + ): void { if (checkArrowFunctions) { validateNode(node); } }, - 'FunctionDeclaration[async = false]'(node: TSESTree.FunctionDeclaration) { + 'FunctionDeclaration[async = false]'( + node: TSESTree.FunctionDeclaration, + ): void { if (checkFunctionDeclarations) { validateNode(node); } }, - 'FunctionExpression[async = false]'(node: TSESTree.FunctionExpression) { + 'FunctionExpression[async = false]'( + node: TSESTree.FunctionExpression, + ): void { if ( node.parent && 'kind' in node.parent && diff --git a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts index a9745be16e0..5b3f430420f 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -26,7 +26,7 @@ export default util.createRule({ return { "CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]"( node: TSESTree.MemberExpression, - ) { + ): void { // Get the symbol of the `sort` method. const tsNode = service.esTreeNodeToTSNodeMap.get(node); const sortSymbol = checker.getSymbolAtLocation(tsNode); diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index cbdd08791d9..ef1092b46db 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -23,7 +23,7 @@ export default util.createRule({ docs: { description: 'Disallow async functions which have no `await` expression', category: 'Best Practices', - recommended: false, + recommended: 'error', }, schema: baseRule.meta.schema, messages: baseRule.meta.messages, @@ -46,7 +46,7 @@ export default util.createRule({ | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression, - ) { + ): void { scopeInfo = { upper: scopeInfo, returnsPromise: false, @@ -79,7 +79,7 @@ export default util.createRule({ | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.ArrowFunctionExpression, - ) { + ): void { if (scopeInfo) { if (!scopeInfo.returnsPromise) { switch (node.type) { @@ -109,7 +109,7 @@ export default util.createRule({ 'FunctionExpression[async = true]:exit': exitFunction, 'ArrowFunctionExpression[async = true]:exit': exitFunction, - ReturnStatement(node: TSESTree.ReturnStatement) { + ReturnStatement(node): void { if (!scopeInfo) { return; } diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 6d68d5f7dfc..df523033bf7 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -83,7 +83,7 @@ export default util.createRule({ } return { - "BinaryExpression[operator='+']"(node: TSESTree.BinaryExpression) { + "BinaryExpression[operator='+']"(node: TSESTree.BinaryExpression): void { const leftType = getNodeType(node.left); const rightType = getNodeType(node.right); diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 8130088eb30..8d1ada467e3 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -16,6 +16,7 @@ export default util.createRule({ docs: { description: 'Require or disallow semicolons instead of ASI', category: 'Stylistic Issues', + // too opinionated to be recommended recommended: false, }, fixable: 'code', @@ -59,7 +60,7 @@ export default util.createRule({ return { ...rules, ...nodesToCheck, - ExportDefaultDeclaration(node) { + ExportDefaultDeclaration(node): void { if (node.declaration.type !== AST_NODE_TYPES.TSInterfaceDeclaration) { rules.ExportDefaultDeclaration(node); } diff --git a/packages/eslint-plugin/src/rules/triple-slash-reference.ts b/packages/eslint-plugin/src/rules/triple-slash-reference.ts index 7d74ab0c603..c5ab5772523 100644 --- a/packages/eslint-plugin/src/rules/triple-slash-reference.ts +++ b/packages/eslint-plugin/src/rules/triple-slash-reference.ts @@ -18,7 +18,7 @@ export default util.createRule({ description: 'Sets preference level for triple slash directives versus ES6-style import declarations', category: 'Best Practices', - recommended: false, + recommended: 'error', }, messages: { tripleSlashReference: @@ -57,7 +57,7 @@ export default util.createRule({ importName: string; })[] = []; - function hasMatchingReference(source: TSESTree.Literal) { + function hasMatchingReference(source: TSESTree.Literal): void { references.forEach(reference => { if (reference.importName === source.value) { context.report({ @@ -71,20 +71,20 @@ export default util.createRule({ }); } return { - ImportDeclaration(node) { + ImportDeclaration(node): void { if (programNode) { const source = node.source as TSESTree.Literal; hasMatchingReference(source); } }, - TSImportEqualsDeclaration(node) { + TSImportEqualsDeclaration(node): void { if (programNode) { const source = (node.moduleReference as TSESTree.TSExternalModuleReference) .expression as TSESTree.Literal; hasMatchingReference(source); } }, - Program(node) { + Program(node): void { if (lib === 'always' && path === 'always' && types == 'always') { return; } diff --git a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts index f5e11f51fb0..d0f1c5b45a4 100644 --- a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts +++ b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts @@ -185,12 +185,12 @@ export default util.createRule({ } return { - TSMappedType(node) { + TSMappedType(node): void { if (node.typeAnnotation) { checkTypeAnnotationSpacing(node.typeAnnotation); } }, - TSTypeAnnotation(node) { + TSTypeAnnotation(node): void { checkTypeAnnotationSpacing(node.typeAnnotation); }, }; diff --git a/packages/eslint-plugin/src/rules/typedef.ts b/packages/eslint-plugin/src/rules/typedef.ts index 3c535467f2c..182568e5748 100644 --- a/packages/eslint-plugin/src/rules/typedef.ts +++ b/packages/eslint-plugin/src/rules/typedef.ts @@ -55,7 +55,7 @@ export default util.createRule<[Options], MessageIds>({ }, ], create(context, [options]) { - function report(location: TSESTree.Node, name?: string) { + function report(location: TSESTree.Node, name?: string): void { context.report({ node: location, messageId: name ? 'expectedTypedefNamed' : 'expectedTypedef', @@ -63,11 +63,13 @@ export default util.createRule<[Options], MessageIds>({ }); } - function getNodeName(node: TSESTree.Parameter | TSESTree.PropertyName) { + function getNodeName( + node: TSESTree.Parameter | TSESTree.PropertyName, + ): string | undefined { return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined; } - function checkParameters(params: TSESTree.Parameter[]) { + function checkParameters(params: TSESTree.Parameter[]): void { for (const param of params) { let annotationNode: TSESTree.Node | undefined; @@ -90,17 +92,17 @@ export default util.createRule<[Options], MessageIds>({ } return { - ArrayPattern(node) { + ArrayPattern(node): void { if (options[OptionKeys.ArrayDestructuring] && !node.typeAnnotation) { report(node); } }, - ArrowFunctionExpression(node) { + ArrowFunctionExpression(node): void { if (options[OptionKeys.ArrowParameter]) { checkParameters(node.params); } }, - ClassProperty(node) { + ClassProperty(node): void { if ( options[OptionKeys.MemberVariableDeclaration] && !node.typeAnnotation @@ -115,19 +117,19 @@ export default util.createRule<[Options], MessageIds>({ }, 'FunctionDeclaration, FunctionExpression'( node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression, - ) { + ): void { if (options[OptionKeys.Parameter]) { checkParameters(node.params); } }, - ObjectPattern(node) { + ObjectPattern(node): void { if (options[OptionKeys.ObjectDestructuring] && !node.typeAnnotation) { report(node); } }, 'TSIndexSignature, TSPropertySignature'( node: TSESTree.TSIndexSignature | TSESTree.TSPropertySignature, - ) { + ): void { if (options[OptionKeys.PropertyDeclaration] && !node.typeAnnotation) { report( node, @@ -137,7 +139,7 @@ export default util.createRule<[Options], MessageIds>({ ); } }, - VariableDeclarator(node) { + VariableDeclarator(node): void { if ( options[OptionKeys.VariableDeclaration] && !node.id.typeAnnotation diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 88892b63417..0db82b2c770 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -25,7 +25,7 @@ export default util.createRule({ category: 'Best Practices', description: 'Enforces unbound methods are called with their expected scope', - recommended: false, + recommended: 'error', }, messages: { unbound: @@ -54,7 +54,7 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); return { - [AST_NODE_TYPES.MemberExpression](node: TSESTree.MemberExpression) { + MemberExpression(node): void { if (isSafeUse(node)) { return; } @@ -73,7 +73,7 @@ export default util.createRule({ }, }); -function isDangerousMethod(symbol: ts.Symbol, ignoreStatic: boolean) { +function isDangerousMethod(symbol: ts.Symbol, ignoreStatic: boolean): boolean { const { valueDeclaration } = symbol; if (!valueDeclaration) { // working around https://github.com/microsoft/TypeScript/issues/31294 diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index 04695fcc302..1c3f747bc51 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -55,6 +55,7 @@ export default util.createRule({ description: 'Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter', category: 'Variables', + // too opinionated to be recommended recommended: false, }, type: 'suggestion', @@ -307,14 +308,14 @@ export default util.createRule({ typeParameters?: TSESTree.TSTypeParameterDeclaration, ): IsTypeParameter { if (typeParameters === undefined) { - return () => false; + return (() => false) as IsTypeParameter; } const set = new Set(); for (const t of typeParameters.params) { set.add(t.name.name); } - return typeName => set.has(typeName); + return (typeName => set.has(typeName)) as IsTypeParameter; } /** True if any of the outer type parameters are used in a signature. */ @@ -476,7 +477,7 @@ export default util.createRule({ function createScope( parent: ScopeNode, typeParameters?: TSESTree.TSTypeParameterDeclaration, - ) { + ): void { currentScope && scopes.push(currentScope); currentScope = { overloads: new Map(), @@ -485,7 +486,7 @@ export default util.createRule({ }; } - function checkScope() { + function checkScope(): void { const failures = checkOverloads( Array.from(currentScope.overloads.values()), currentScope.typeParameters, @@ -494,7 +495,7 @@ export default util.createRule({ currentScope = scopes.pop()!; } - function addOverload(signature: OverloadNode, key?: string) { + function addOverload(signature: OverloadNode, key?: string): void { key = key || getOverloadKey(signature); if (currentScope && signature.parent === currentScope.parent && key) { const overloads = currentScope.overloads.get(key); @@ -513,15 +514,15 @@ export default util.createRule({ return { Program: createScope, TSModuleBlock: createScope, - TSInterfaceDeclaration(node) { + TSInterfaceDeclaration(node): void { createScope(node.body, node.typeParameters); }, - ClassDeclaration(node) { + ClassDeclaration(node): void { createScope(node.body, node.typeParameters); }, TSTypeLiteral: createScope, // collect overloads - TSDeclareFunction(node) { + TSDeclareFunction(node): void { if (node.id && !node.body) { addOverload(node, node.id.name); } @@ -529,12 +530,12 @@ export default util.createRule({ TSCallSignatureDeclaration: addOverload, TSConstructSignatureDeclaration: addOverload, TSMethodSignature: addOverload, - TSAbstractMethodDefinition(node) { + TSAbstractMethodDefinition(node): void { if (!node.value.body) { addOverload(node); } }, - MethodDefinition(node) { + MethodDefinition(node): void { if (!node.value.body) { addOverload(node); } diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 30587b336ed..cae887c229f 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -11,14 +11,14 @@ import { /** * Check if the context file name is *.d.ts or *.d.tsx */ -export function isDefinitionFile(fileName: string) { +export function isDefinitionFile(fileName: string): boolean { return /\.d\.tsx?$/i.test(fileName || ''); } /** * Upper cases the first character or the string */ -export function upperCaseFirst(str: string) { +export function upperCaseFirst(str: string): string { return str[0].toUpperCase() + str.slice(1); } diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/eslint-plugin/src/util/types.ts index 83a8bbabf57..6f769d7f950 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/eslint-plugin/src/util/types.ts @@ -186,7 +186,10 @@ export function isTypeFlagSet( /** * @returns Whether a type is an instance of the parent type, including for the parent's base types. */ -export const typeIsOrHasBaseType = (type: ts.Type, parentType: ts.Type) => { +export function typeIsOrHasBaseType( + type: ts.Type, + parentType: ts.Type, +): boolean { if (type.symbol === undefined || parentType.symbol === undefined) { return false; } @@ -208,4 +211,4 @@ export const typeIsOrHasBaseType = (type: ts.Type, parentType: ts.Type) => { } return false; -}; +} diff --git a/packages/eslint-plugin/tests/RuleTester.ts b/packages/eslint-plugin/tests/RuleTester.ts index fe3d06d4fc8..978adc10966 100644 --- a/packages/eslint-plugin/tests/RuleTester.ts +++ b/packages/eslint-plugin/tests/RuleTester.ts @@ -68,7 +68,7 @@ class RuleTester extends TSESLint.RuleTester { } } -function getFixturesRootDir() { +function getFixturesRootDir(): string { return path.join(process.cwd(), 'tests/fixtures/'); } diff --git a/packages/eslint-plugin/tests/rules/indent/utils.ts b/packages/eslint-plugin/tests/rules/indent/utils.ts index 72cedd3ea64..badfbc1c3c6 100644 --- a/packages/eslint-plugin/tests/rules/indent/utils.ts +++ b/packages/eslint-plugin/tests/rules/indent/utils.ts @@ -17,6 +17,7 @@ type MessageIds = InferMessageIdsTypeFromRule; * @returns The template literal, with spaces removed from all lines */ export function unIndent(strings: TemplateStringsArray): string { + const WHITESPACE_REGEX = / */u; const templateValue = strings[0]; const lines = templateValue .replace(/^\n/u, '') @@ -24,7 +25,7 @@ export function unIndent(strings: TemplateStringsArray): string { .split('\n'); const lineIndents = lines .filter(line => line.trim()) - .map(line => / */u.exec(line)![0].length); + .map(line => WHITESPACE_REGEX.exec(line)![0].length); const minLineIndent = Math.min(...lineIndents); return lines.map(line => line.slice(minLineIndent)).join('\n'); diff --git a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts index c1ddce12186..03723eb9515 100644 --- a/packages/eslint-plugin/tests/rules/no-this-alias.test.ts +++ b/packages/eslint-plugin/tests/rules/no-this-alias.test.ts @@ -68,6 +68,11 @@ declare module 'foo' { }, { code: 'const { props, state } = this;', + options: [ + { + allowDestructuring: false, + }, + ], errors: [destructureError], }, { @@ -104,6 +109,11 @@ class TestClass { } } `, + options: [ + { + allowDestructuring: false, + }, + ], errors: [ idError, idError, diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts index d09724e8eee..45bb8c80db1 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts @@ -10,10 +10,12 @@ const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', }); -function error(messages: { message: string; line: number; column: number }[]) { - // the base rule doesn't have messageIds +// the base rule doesn't have messageIds +function error( + messages: { message: string; line: number; column: number }[], // eslint-disable-next-line @typescript-eslint/no-explicit-any - return messages as any[]; +): any[] { + return messages; } ruleTester.run('no-unused-vars', rule, { diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index 5e293018eb4..d7f5fb29afd 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -2,8 +2,11 @@ import { TSESLint } from '@typescript-eslint/experimental-utils'; import chalk from 'chalk'; import fs from 'fs'; import path from 'path'; +import { format, resolveConfig } from 'prettier'; import rules from '../src/rules'; +const prettierConfig = resolveConfig(__dirname); + interface LinterConfigRules { [name: string]: | TSESLint.Linter.RuleLevel @@ -23,29 +26,40 @@ const BASE_RULES_TO_BE_OVERRIDDEN = new Set([ 'func-call-spacing', 'indent', 'no-array-constructor', + 'no-empty-function', 'no-extra-parens', 'no-magic-numbers', 'no-unused-vars', 'no-use-before-define', 'no-useless-constructor', + 'require-await', 'semi', ]); +// list of rules from the base plugin that we think should be turned on for typescript code +const BASE_RULES_THAT_ARE_RECOMMENDED = new Set([ + 'no-var', + 'prefer-const', + 'prefer-rest-params', + 'prefer-spread', +]); -const ruleEntries = Object.entries(rules); +const ruleEntries = Object.entries(rules).sort((a, b) => + a[0].localeCompare(b[0]), +); /** * Helper function reduces records to key - value pairs. * @param config * @param entry */ -const reducer = ( +function reducer( config: LinterConfigRules, entry: [string, TSESLint.RuleModule], settings: { errorLevel?: 'error' | 'warn'; filterDeprecated: boolean; }, -) => { +): LinterConfigRules { const key = entry[0]; const value = entry[1]; @@ -81,13 +95,17 @@ const reducer = ( config[ruleName] = usedSetting; return config; -}; +} /** * Helper function writes configuration. */ function writeConfig(config: LinterConfig, filePath: string): void { - fs.writeFileSync(filePath, `${JSON.stringify(config, null, 2)}\n`); + const configStr = format(JSON.stringify(config), { + parser: 'json', + ...prettierConfig, + }); + fs.writeFileSync(filePath, configStr); } const baseConfig: LinterConfig = { @@ -117,14 +135,18 @@ console.log(); console.log( '------------------------------ recommended.json ------------------------------', ); +const recommendedRules = ruleEntries + .filter(entry => !!entry[1].meta.docs.recommended) + .reduce( + (config, entry) => reducer(config, entry, { filterDeprecated: false }), + {}, + ); +BASE_RULES_THAT_ARE_RECOMMENDED.forEach(ruleName => { + recommendedRules[ruleName] = 'error'; +}); const recommendedConfig: LinterConfig = { extends: './configs/base.json', - rules: ruleEntries - .filter(entry => !!entry[1].meta.docs.recommended) - .reduce( - (config, entry) => reducer(config, entry, { filterDeprecated: false }), - {}, - ), + rules: recommendedRules, }; writeConfig( recommendedConfig, diff --git a/packages/eslint-plugin/tools/validate-configs/checkConfigAll.ts b/packages/eslint-plugin/tools/validate-configs/checkConfigAll.ts index 84981b8816e..fab57fe20cf 100644 --- a/packages/eslint-plugin/tools/validate-configs/checkConfigAll.ts +++ b/packages/eslint-plugin/tools/validate-configs/checkConfigAll.ts @@ -3,13 +3,13 @@ import { logRule } from '../log'; const prefix = '@typescript-eslint/'; -function checkConfigAll() { +function checkConfigAll(): boolean { const { rules } = plugin; const all = plugin.configs.all.rules; const allNames = new Set(Object.keys(all)); - return Object.entries(rules).reduce((acc, [ruleName, rule]) => { + return Object.entries(rules).reduce((acc, [ruleName, rule]) => { if (!rule.meta.deprecated) { const prefixed = `${prefix}${ruleName}` as keyof typeof all; if (allNames.has(prefixed)) { diff --git a/packages/eslint-plugin/tools/validate-configs/checkConfigRecommended.ts b/packages/eslint-plugin/tools/validate-configs/checkConfigRecommended.ts index 21f2faa876d..ae256143112 100644 --- a/packages/eslint-plugin/tools/validate-configs/checkConfigRecommended.ts +++ b/packages/eslint-plugin/tools/validate-configs/checkConfigRecommended.ts @@ -3,13 +3,13 @@ import { logRule } from '../log'; const prefix = '@typescript-eslint/'; -function checkConfigRecommended() { +function checkConfigRecommended(): boolean { const { rules } = plugin; const recommended = plugin.configs.recommended.rules; const recommendedNames = new Set(Object.keys(recommended)); - return Object.entries(rules).reduce((acc, [ruleName, rule]) => { + return Object.entries(rules).reduce((acc, [ruleName, rule]) => { if (!rule.meta.deprecated && rule.meta.docs.recommended !== false) { const prefixed = `${prefix}${ruleName}` as keyof typeof recommended; if (recommendedNames.has(prefixed)) { diff --git a/packages/eslint-plugin/tools/validate-docs/validate-table-structure.ts b/packages/eslint-plugin/tools/validate-docs/validate-table-structure.ts index e9d339c10c2..ed6a8131edb 100644 --- a/packages/eslint-plugin/tools/validate-docs/validate-table-structure.ts +++ b/packages/eslint-plugin/tools/validate-docs/validate-table-structure.ts @@ -3,6 +3,7 @@ import chalk from 'chalk'; import marked from 'marked'; import { logError } from '../log'; +const RULE_LINK_REGEX = /\[`@typescript-eslint\/(.+)`\]/; function validateTableStructure( rules: Record>>, rulesTable: marked.Tokens.Table, @@ -13,7 +14,7 @@ function validateTableStructure( let hasErrors = false; rulesTable.cells.forEach((row, rowIndex) => { - const match = /\[`@typescript-eslint\/(.+)`\]/.exec(row[0]); + const match = RULE_LINK_REGEX.exec(row[0]); if (!match) { logError(chalk.bold(`Unable to parse link in row ${rowIndex}:`), row[0]); hasErrors = true; diff --git a/packages/experimental-utils/src/eslint-utils/RuleCreator.ts b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts index e14242fca72..3edb71e5a55 100644 --- a/packages/experimental-utils/src/eslint-utils/RuleCreator.ts +++ b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts @@ -42,7 +42,7 @@ export function RuleCreator(urlCreator: (ruleName: string) => string) { url: urlCreator(name), }, }, - create(context) { + create(context): TRuleListener { const optionsWithDefault = applyDefault( defaultOptions, context.options, diff --git a/packages/experimental-utils/src/eslint-utils/deepMerge.ts b/packages/experimental-utils/src/eslint-utils/deepMerge.ts index 966a0db0821..3db67a59407 100644 --- a/packages/experimental-utils/src/eslint-utils/deepMerge.ts +++ b/packages/experimental-utils/src/eslint-utils/deepMerge.ts @@ -18,7 +18,10 @@ export function isObjectNotArray( * @param second The second object * @returns a new object */ -export function deepMerge(first: ObjectLike = {}, second: ObjectLike = {}) { +export function deepMerge( + first: ObjectLike = {}, + second: ObjectLike = {}, +): Record { // get the unique set of keys across both objects const keys = new Set(Object.keys(first).concat(Object.keys(second))); diff --git a/packages/parser/src/analyze-scope.ts b/packages/parser/src/analyze-scope.ts index 6c7e5a38428..1b98c064db0 100644 --- a/packages/parser/src/analyze-scope.ts +++ b/packages/parser/src/analyze-scope.ts @@ -21,7 +21,7 @@ function overrideDefine( this: TSESLintScope.Scope, node: TSESTree.Node, definition: TSESLintScope.Definition, - ) { + ): void { define.call(this, node, definition); // Set `variable.eslintUsed` to tell ESLint that the variable is exported. @@ -147,7 +147,7 @@ class Referencer extends TSESLintScope.Referencer { const upperScope = this.currentScope(); // Process the name. - if (type === 'FunctionDeclaration' && id) { + if (type === AST_NODE_TYPES.FunctionDeclaration && id) { upperScope.__define( id, new TSESLintScope.Definition( @@ -166,14 +166,14 @@ class Referencer extends TSESLintScope.Referencer { const def = defs[i]; if ( def.type === 'FunctionName' && - def.node.type === 'TSDeclareFunction' + def.node.type === AST_NODE_TYPES.TSDeclareFunction ) { defs.splice(i, 1); identifiers.splice(i, 1); break; } } - } else if (type === 'FunctionExpression' && id) { + } else if (type === AST_NODE_TYPES.FunctionExpression && id) { scopeManager.__nestFunctionExpressionNameScope(node); } @@ -213,7 +213,7 @@ class Referencer extends TSESLintScope.Referencer { this.visit(returnType); // Process the body. - if (body && body.type === 'BlockStatement') { + if (body && body.type === AST_NODE_TYPES.BlockStatement) { this.visitChildren(body); } else { this.visit(body); @@ -732,7 +732,7 @@ class Referencer extends TSESLintScope.Referencer { return; } - if (id && id.type === 'Identifier') { + if (id && id.type === AST_NODE_TYPES.Identifier) { scope.__define( id, new TSESLintScope.Definition( @@ -777,7 +777,7 @@ class Referencer extends TSESLintScope.Referencer { */ TSImportEqualsDeclaration(node: TSESTree.TSImportEqualsDeclaration): void { const { id, moduleReference } = node; - if (id && id.type === 'Identifier') { + if (id && id.type === AST_NODE_TYPES.Identifier) { this.currentScope().__define( id, new TSESLintScope.Definition( @@ -809,7 +809,7 @@ class Referencer extends TSESLintScope.Referencer { scopeManager.__currentScope = globalScope; // Skip TSModuleBlock to avoid to create that block scope. - if (node.body && node.body.type === 'TSModuleBlock') { + if (node.body && node.body.type === AST_NODE_TYPES.TSModuleBlock) { node.body.body.forEach(this.visit, this); } @@ -845,7 +845,7 @@ class Referencer extends TSESLintScope.Referencer { export function analyzeScope( ast: TSESTree.Program, parserOptions: ParserOptions, -) { +): ScopeManager { const options = { ignoreEval: true, optimistic: false, diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index fb5142f9b37..830a282da1e 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -28,7 +28,7 @@ interface ParseForESLintResult { function validateBoolean( value: boolean | undefined, - fallback: boolean = false, + fallback = false, ): boolean { if (typeof value !== 'boolean') { return fallback; @@ -44,7 +44,10 @@ export const version = packageJSON.version; export const Syntax = Object.freeze(AST_NODE_TYPES); -export function parse(code: string, options?: ParserOptions) { +export function parse( + code: string, + options?: ParserOptions, +): ParseForESLintResult['ast'] { return parseForESLint(code, options).ast; } diff --git a/packages/parser/src/scope/scope-manager.ts b/packages/parser/src/scope/scope-manager.ts index 648e24b77f8..c179bd512d3 100644 --- a/packages/parser/src/scope/scope-manager.ts +++ b/packages/parser/src/scope/scope-manager.ts @@ -13,12 +13,14 @@ export class ScopeManager extends TSESLintScope.ScopeManager { } /** @internal */ - __nestEnumScope(node: TSESTree.TSEnumDeclaration) { + __nestEnumScope(node: TSESTree.TSEnumDeclaration): TSESLintScope.Scope { return this.__nestScope(new EnumScope(this, this.__currentScope, node)); } /** @internal */ - __nestEmptyFunctionScope(node: TSESTree.TSDeclareFunction) { + __nestEmptyFunctionScope( + node: TSESTree.TSDeclareFunction, + ): TSESLintScope.Scope { return this.__nestScope( new EmptyFunctionScope(this, this.__currentScope, node), ); diff --git a/packages/parser/src/simple-traverse.ts b/packages/parser/src/simple-traverse.ts index 10f58918799..a616f239a7b 100644 --- a/packages/parser/src/simple-traverse.ts +++ b/packages/parser/src/simple-traverse.ts @@ -26,7 +26,7 @@ class SimpleTraverser { this.enter = enter; } - traverse(node: unknown, parent: TSESTree.Node | undefined) { + traverse(node: unknown, parent: TSESTree.Node | undefined): void { if (!isValidNode(node)) { return; } @@ -54,6 +54,6 @@ class SimpleTraverser { export function simpleTraverse( startingNode: TSESTree.Node, options: SimpleTraverseOptions, -) { +): void { new SimpleTraverser(options).traverse(startingNode, undefined); } diff --git a/packages/parser/tests/lib/basics.ts b/packages/parser/tests/lib/basics.ts index d526745e341..c06e8e57be1 100644 --- a/packages/parser/tests/lib/basics.ts +++ b/packages/parser/tests/lib/basics.ts @@ -39,7 +39,7 @@ export const Price: React.SFC = function Price(props) {} linter.defineRule('test', { create(context) { return { - TSTypeReference(node) { + TSTypeReference(node): void { const name = context.getSourceCode().getText(node.typeName); context.report({ node, diff --git a/packages/parser/tests/lib/jsx.ts b/packages/parser/tests/lib/jsx.ts index 4d7f6a3f9bf..530b26c444b 100644 --- a/packages/parser/tests/lib/jsx.ts +++ b/packages/parser/tests/lib/jsx.ts @@ -27,7 +27,7 @@ describe('JSX', () => { * Test each fixture file */ function testFixture(fixturesDir: string, useJSXTextNode: boolean) { - return (filename: string) => { + return (filename: string): void => { const code = fs.readFileSync(filename, 'utf8'); const config = { useJSXTextNode, diff --git a/packages/parser/tests/tools/scope-analysis.ts b/packages/parser/tests/tools/scope-analysis.ts index e7aab1d9951..373b863be81 100644 --- a/packages/parser/tests/tools/scope-analysis.ts +++ b/packages/parser/tests/tools/scope-analysis.ts @@ -8,20 +8,20 @@ export class ReferenceResolver { this.map = new Map(); } - resolve(obj: any, properties: any) { + resolve(obj: any, properties: any): any { const resolved = Object.assign({ $id: this.map.size }, properties); this.map.set(obj, resolved); return resolved; } - ref(obj: any) { + ref(obj: any): any { if (typeof obj !== 'object' || obj === null) { return obj; } - const { map } = this; + const map = this.map; return { - get $ref() { + get $ref(): any { return map.get(obj).$id; }, }; @@ -34,7 +34,7 @@ export class ReferenceResolver { * @param {ASTNode} node The AST node object. * @returns {Object} The object that can be used for JSON.stringify. */ -export function nodeToJSON(node: any) { +export function nodeToJSON(node: any): any { if (!node) { return node; } @@ -52,7 +52,7 @@ export function nodeToJSON(node: any) { * @param {ReferenceResolver} resolver The reference resolver. * @returns {Object} The object that can be used for JSON.stringify. */ -export function variableToJSON(variable: any, resolver: any) { +export function variableToJSON(variable: any, resolver: any): any { const { name, eslintUsed } = variable; const defs = variable.defs.map((d: any) => ({ type: d.type, @@ -80,7 +80,7 @@ export function variableToJSON(variable: any, resolver: any) { * @param {ReferenceResolver} resolver The reference resolver. * @returns {Object} The object that can be used for JSON.stringify. */ -export function referenceToJSON(reference: any, resolver: any) { +export function referenceToJSON(reference: any, resolver: any): any { const kind = `${reference.isRead() ? 'r' : ''}${ reference.isWrite() ? 'w' : '' }`; @@ -104,7 +104,10 @@ export function referenceToJSON(reference: any, resolver: any) { * @param {ReferenceResolver} resolver The reference resolver. * @returns {Object} The object that can be used for JSON.stringify. */ -export function scopeToJSON(scope: any, resolver = new ReferenceResolver()) { +export function scopeToJSON( + scope: any, + resolver = new ReferenceResolver(), +): any { const { type, functionExpressionScope, isStrict } = scope; const block = nodeToJSON(scope.block); const variables = scope.variables.map((v: any) => @@ -142,7 +145,7 @@ export function scopeToJSON(scope: any, resolver = new ReferenceResolver()) { }); } -export function getScopeTree(scopeManager: any) { +export function getScopeTree(scopeManager: any): any { const { globalScope } = scopeManager; // Do the postprocess to test. diff --git a/packages/parser/tests/tools/test-utils.ts b/packages/parser/tests/tools/test-utils.ts index 1ce769a521b..28dd40d2e07 100644 --- a/packages/parser/tests/tools/test-utils.ts +++ b/packages/parser/tests/tools/test-utils.ts @@ -18,7 +18,7 @@ const defaultConfig = { * @param ast the AST object * @returns copy of the AST object */ -function getRaw(ast: TSESTree.Program) { +function getRaw(ast: TSESTree.Program): TSESTree.Program { return JSON.parse( JSON.stringify(ast, (key, value) => { if ((key === 'start' || key === 'end') && typeof value === 'number') { @@ -39,18 +39,18 @@ function getRaw(ast: TSESTree.Program) { export function createSnapshotTestBlock( code: string, config: ParserOptions = {}, -) { +): () => void { config = Object.assign({}, defaultConfig, config); /** * @returns {Object} the AST object */ - function parse() { + function parse(): TSESTree.Program { const ast = parser.parseForESLint(code, config).ast; return getRaw(ast); } - return () => { + return (): void => { try { const result = parse(); expect(result).toMatchSnapshot(); @@ -77,18 +77,19 @@ export function createSnapshotTestBlock( export function createScopeSnapshotTestBlock( code: string, config: ParserOptions = {}, -) { +): () => void { config = Object.assign({}, defaultConfig, config); /** * @returns {Object} the AST object */ - function parse() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function parse(): any { const result = parser.parseForESLint(code, config); return getScopeTree(result.scopeManager); } - return () => { + return (): void => { try { const result = parse(); expect(result).toMatchSnapshot(); @@ -123,7 +124,7 @@ export function formatSnapshotName( filename: string, fixturesDir: string, fileExtension = '.js', -) { +): string { return `fixtures/${filename .replace(fixturesDir + '/', '') .replace(fileExtension, '')}`; diff --git a/packages/typescript-estree/src/ast-converter.ts b/packages/typescript-estree/src/ast-converter.ts index 9cb2bdc974a..fffb9ea15cf 100644 --- a/packages/typescript-estree/src/ast-converter.ts +++ b/packages/typescript-estree/src/ast-converter.ts @@ -1,14 +1,15 @@ import { SourceFile } from 'typescript'; -import { convertError, Converter } from './convert'; +import { convertError, Converter, ASTMaps } from './convert'; import { convertComments } from './convert-comments'; import { convertTokens } from './node-utils'; import { Extra } from './parser-options'; +import { TSESTree } from './ts-estree'; export function astConverter( ast: SourceFile, extra: Extra, shouldPreserveNodeMaps: boolean, -) { +): { estree: TSESTree.Program; astMaps: ASTMaps | undefined } { /** * The TypeScript compiler produced fundamental parse errors when parsing the * source. diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index dedae68dd17..3a7d2de99dc 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -19,8 +19,10 @@ import { isESTreeClassMember, isOptional, unescapeStringLiteralText, + TSError, } from './node-utils'; import { AST_NODE_TYPES, TSESTree, TSNode } from './ts-estree'; +import { ParserWeakMap } from './parser-options'; const SyntaxKind = ts.SyntaxKind; @@ -35,7 +37,7 @@ interface ConverterOptions { * @param error the error object * @returns converted error object */ -export function convertError(error: any) { +export function convertError(error: any): TSError { return createError( error.file, error.start, @@ -43,14 +45,19 @@ export function convertError(error: any) { ); } +export interface ASTMaps { + esTreeNodeToTSNodeMap: ParserWeakMap; + tsNodeToESTreeNodeMap: ParserWeakMap; +} + export class Converter { private readonly ast: ts.SourceFile; private readonly options: ConverterOptions; private readonly esTreeNodeToTSNodeMap = new WeakMap(); private readonly tsNodeToESTreeNodeMap = new WeakMap(); - private allowPattern: boolean = false; - private inTypeMode: boolean = false; + private allowPattern = false; + private inTypeMode = false; /** * Converts a TypeScript node into an ESTree node @@ -63,7 +70,7 @@ export class Converter { this.options = options; } - getASTMaps() { + getASTMaps(): ASTMaps { return { esTreeNodeToTSNodeMap: this.esTreeNodeToTSNodeMap, tsNodeToESTreeNodeMap: this.tsNodeToESTreeNodeMap, @@ -168,7 +175,7 @@ export class Converter { private registerTSNodeInNodeMap( node: ts.Node, result: TSESTree.BaseNode | null, - ) { + ): void { if (result && this.options.shouldPreserveNodeMaps) { if (!this.tsNodeToESTreeNodeMap.has(node)) { this.tsNodeToESTreeNodeMap.set(node, result); diff --git a/packages/typescript-estree/src/node-utils.ts b/packages/typescript-estree/src/node-utils.ts index f1666635b11..c23daf6e317 100644 --- a/packages/typescript-estree/src/node-utils.ts +++ b/packages/typescript-estree/src/node-utils.ts @@ -644,6 +644,13 @@ export function getNodeContainer( return container!; } +export interface TSError { + index: number; + lineNumber: number; + column: number; + message: string; +} + /** * @param ast the AST object * @param start the index at which the error starts @@ -654,7 +661,7 @@ export function createError( ast: ts.SourceFile, start: number, message: string, -) { +): TSError { const loc = ast.getLineAndCharacterOfPosition(start); return { index: start, @@ -668,7 +675,7 @@ export function createError( * @param n the TSNode * @param ast the TS AST */ -export function nodeHasTokens(n: ts.Node, ast: ts.SourceFile) { +export function nodeHasTokens(n: ts.Node, ast: ts.SourceFile): boolean { // If we have a token or node that has a non-zero width, it must have tokens. // Note: getWidth() does not take trivia into account. return n.kind === SyntaxKind.EndOfFileToken diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 564114d7ccb..f215fa44492 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -33,7 +33,7 @@ let warnedAboutTSVersion = false; * * @param options Parser options */ -function getFileName({ jsx }: { jsx?: boolean }) { +function getFileName({ jsx }: { jsx?: boolean }): string { return jsx ? 'estree.tsx' : 'estree.ts'; } @@ -62,6 +62,11 @@ function resetExtra(): void { }; } +interface ASTAndProgram { + ast: ts.SourceFile; + program: ts.Program | undefined; +} + /** * @param code The code of the file being linted * @param options The config object @@ -71,7 +76,7 @@ function getASTFromProject( code: string, options: TSESTreeOptions, createDefaultProgram: boolean, -) { +): ASTAndProgram | undefined { const filePath = options.filePath || getFileName(options); const astAndProgram = firstDefined( calculateProjectParserOptions(code, filePath, extra), @@ -95,7 +100,10 @@ function getASTFromProject( * @param options The config object * @returns If found, returns the source file corresponding to the code and the containing program */ -function getASTAndDefaultProject(code: string, options: TSESTreeOptions) { +function getASTAndDefaultProject( + code: string, + options: TSESTreeOptions, +): ASTAndProgram | undefined { const fileName = options.filePath || getFileName(options); const program = createProgram(code, fileName, extra); const ast = program && program.getSourceFile(fileName); @@ -106,7 +114,7 @@ function getASTAndDefaultProject(code: string, options: TSESTreeOptions) { * @param code The code of the file being linted * @returns Returns a new source file and program corresponding to the linted code */ -function createNewProgram(code: string) { +function createNewProgram(code: string): ASTAndProgram { const FILENAME = getFileName(extra); const compilerHost: ts.CompilerHost = { @@ -170,7 +178,7 @@ function getProgramAndAST( options: TSESTreeOptions, shouldProvideParserServices: boolean, createDefaultProgram: boolean, -) { +): ASTAndProgram | undefined { return ( (shouldProvideParserServices && getASTFromProject(code, options, createDefaultProgram)) || @@ -293,7 +301,7 @@ function warnAboutTSVersion(): void { // Parser //------------------------------------------------------------------------------ -type AST = TSESTree.Program & +export type AST = TSESTree.Program & (T['range'] extends true ? { range: [number, number] } : {}) & (T['tokens'] extends true ? { tokens: TSESTree.Token[] } : {}) & (T['comment'] extends true ? { comments: TSESTree.Comment[] } : {}); @@ -403,7 +411,7 @@ export function parseAndGenerateServices< options, shouldProvideParserServices, extra.createDefaultProgram, - ); + )!; /** * Determine whether or not two-way maps of converted AST nodes should be preserved * during the conversion process diff --git a/packages/typescript-estree/src/tsconfig-parser.ts b/packages/typescript-estree/src/tsconfig-parser.ts index 09199053349..88c63171545 100644 --- a/packages/typescript-estree/src/tsconfig-parser.ts +++ b/packages/typescript-estree/src/tsconfig-parser.ts @@ -34,7 +34,7 @@ const parsedFilesSeen = new Set(); * Clear tsconfig caches. * Primarily used for testing. */ -export function clearCaches() { +export function clearCaches(): void { knownWatchProgramMap.clear(); watchCallbackTrackingMap.clear(); parsedFilesSeen.clear(); @@ -58,7 +58,7 @@ function diagnosticReporter(diagnostic: ts.Diagnostic): void { ); } -const noopFileWatcher = { close: () => {} }; +const noopFileWatcher = { close: (): void => {} }; function getTsconfigPath(tsconfigPath: string, extra: Extra): string { return path.isAbsolute(tsconfigPath) @@ -118,7 +118,7 @@ export function calculateProjectParserOptions( // ensure readFile reads the code being linted instead of the copy on disk const oldReadFile = watchCompilerHost.readFile; - watchCompilerHost.readFile = (filePath, encoding) => + watchCompilerHost.readFile = (filePath, encoding): string | undefined => path.normalize(filePath) === path.normalize(currentLintOperationState.filePath) ? currentLintOperationState.code @@ -128,7 +128,7 @@ export function calculateProjectParserOptions( watchCompilerHost.onUnRecoverableConfigFileDiagnostic = diagnosticReporter; // ensure process doesn't emit programs - watchCompilerHost.afterProgramCreate = program => { + watchCompilerHost.afterProgramCreate = (program): void => { // report error if there are any errors in the config file const configFileDiagnostics = program .getConfigFileParsingDiagnostics() @@ -143,18 +143,20 @@ export function calculateProjectParserOptions( }; // register callbacks to trigger program updates without using fileWatchers + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type watchCompilerHost.watchFile = (fileName, callback) => { const normalizedFileName = path.normalize(fileName); watchCallbackTrackingMap.set(normalizedFileName, callback); return { - close: () => { + close: (): void => { watchCallbackTrackingMap.delete(normalizedFileName); }, }; }; // ensure fileWatchers aren't created for directories - watchCompilerHost.watchDirectory = () => noopFileWatcher; + watchCompilerHost.watchDirectory = (): typeof noopFileWatcher => + noopFileWatcher; // we're using internal typescript APIs which aren't on the types /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -163,8 +165,9 @@ export function calculateProjectParserOptions( .onCachedDirectoryStructureHostCreate; (watchCompilerHost as any).onCachedDirectoryStructureHostCreate = ( host: any, - ) => { + ): void => { const oldReadDirectory = host.readDirectory; + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type host.readDirectory = ( path: string, extensions?: readonly string[], @@ -206,7 +209,11 @@ export function calculateProjectParserOptions( * @param extra.project Provided tsconfig paths * @returns The program containing just the file being linted and associated library files */ -export function createProgram(code: string, filePath: string, extra: Extra) { +export function createProgram( + code: string, + filePath: string, + extra: Extra, +): ts.Program | undefined { if (!extra.projects || extra.projects.length !== 1) { return undefined; } @@ -225,7 +232,7 @@ export function createProgram(code: string, filePath: string, extra: Extra) { const compilerHost = ts.createCompilerHost(commandLine.options, true); const oldReadFile = compilerHost.readFile; - compilerHost.readFile = (fileName: string) => + compilerHost.readFile = (fileName: string): string | undefined => path.normalize(fileName) === path.normalize(filePath) ? code : oldReadFile(fileName); diff --git a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts index 4b8e05d166b..64f2453fc60 100644 --- a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts +++ b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts @@ -33,8 +33,6 @@ const sharedFixturesDirPath = path.join( class FixturesTester { protected fixtures: FixturePatternConfig[] = []; - constructor() {} - /** * Utility to generate a FixturePatternConfig object containing the glob pattern for specific subsections of the fixtures/ directory, * including the capability to ignore specific nested patterns. @@ -45,7 +43,7 @@ class FixturesTester { public addFixturePatternConfig( fixturesSubPath: string, config: CreateFixturePatternConfig = {}, - ) { + ): void { let _fixturesDirPath = fixturesDirPath; if (!fs.existsSync(path.join(fixturesDirPath, fixturesSubPath))) { _fixturesDirPath = sharedFixturesDirPath; diff --git a/packages/typescript-estree/tests/ast-alignment/parse.ts b/packages/typescript-estree/tests/ast-alignment/parse.ts index 43c23ce44d7..7fba488c78d 100644 --- a/packages/typescript-estree/tests/ast-alignment/parse.ts +++ b/packages/typescript-estree/tests/ast-alignment/parse.ts @@ -1,12 +1,17 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import { ParserPlugin } from '@babel/parser'; import codeFrame from 'babel-code-frame'; import * as parser from '../../src/parser'; import * as parseUtils from './utils'; -function createError(message: string, line: number, column: number) { +function createError( + message: string, + line: number, + column: number, +): SyntaxError { // Construct an error similar to the ones thrown by Babylon. const error = new SyntaxError(`${message} (${line}:${column})`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any (error as any).loc = { line, column, @@ -14,7 +19,7 @@ function createError(message: string, line: number, column: number) { return error; } -function parseWithBabelParser(text: string, jsx: boolean = true) { +function parseWithBabelParser(text: string, jsx = true): any { const babel = require('@babel/parser'); const plugins: ParserPlugin[] = [ 'typescript', @@ -40,7 +45,7 @@ function parseWithBabelParser(text: string, jsx: boolean = true) { }); } -function parseWithTypeScriptESTree(text: string, jsx: boolean = true) { +function parseWithTypeScriptESTree(text: string, jsx = true): parser.AST { try { const result = parser.parseAndGenerateServices(text, { loc: true, @@ -69,12 +74,14 @@ interface ASTComparisonParseOptions { jsx?: boolean; } -export function parse(text: string, opts: ASTComparisonParseOptions) { +export function parse( + text: string, + opts: ASTComparisonParseOptions, +): { parseError: any | null; ast: any | null } { /** * Always return a consistent interface, there will be times when we expect both * parsers to fail to parse the invalid source. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any const result: { parseError: any | null; ast: any | null } = { parseError: null, ast: null, diff --git a/packages/typescript-estree/tests/ast-alignment/utils.ts b/packages/typescript-estree/tests/ast-alignment/utils.ts index 43be2143e78..563fd19cc30 100644 --- a/packages/typescript-estree/tests/ast-alignment/utils.ts +++ b/packages/typescript-estree/tests/ast-alignment/utils.ts @@ -26,7 +26,7 @@ export function omitDeep( root: any, keysToOmit: { key: string; predicate: Function }[], nodes: Record void> = {}, -) { +): any { function shouldOmit(keyName: string, val: any): boolean { if (keysToOmit && keysToOmit.length) { return keysToOmit.some( @@ -36,7 +36,7 @@ export function omitDeep( return false; } - function visit(node: any, parent: any) { + function visit(node: any, parent: any): void { if (!node) { return; } @@ -72,8 +72,8 @@ export function omitDeep( /** * Common predicates for Babylon AST preprocessing */ -const always = () => true; -const ifNumber = (val: any) => typeof val === 'number'; +const always = (): boolean => true; +const ifNumber = (val: any): boolean => typeof val === 'number'; /** * - Babylon wraps the "Program" node in an extra "File" node, normalize this for simplicity for now... @@ -290,7 +290,7 @@ export function preprocessBabylonAST(ast: any): any { export function removeLocationDataAndSourceTypeFromProgramNode( ast: any, ignoreSourceType: boolean, -) { +): any { delete ast.loc; delete ast.range; if (ignoreSourceType) { diff --git a/packages/typescript-estree/tests/lib/convert.ts b/packages/typescript-estree/tests/lib/convert.ts index 4a5ac51be55..2a275c53fb4 100644 --- a/packages/typescript-estree/tests/lib/convert.ts +++ b/packages/typescript-estree/tests/lib/convert.ts @@ -100,7 +100,7 @@ describe('convert', () => { instance.convertProgram(); const maps = instance.getASTMaps(); - function checkMaps(child: any) { + function checkMaps(child: any): void { child.forEachChild((node: any) => { if ( node.kind !== ts.SyntaxKind.EndOfFileToken && @@ -134,7 +134,7 @@ describe('convert', () => { instance.convertProgram(); const maps = instance.getASTMaps(); - function checkMaps(child: any) { + function checkMaps(child: any): void { child.forEachChild((node: any) => { if ( node.kind !== ts.SyntaxKind.EndOfFileToken && @@ -167,7 +167,7 @@ describe('convert', () => { const program = instance.convertProgram(); const maps = instance.getASTMaps(); - function checkMaps(child: any) { + function checkMaps(child: any): void { child.forEachChild((node: any) => { if (node.kind !== ts.SyntaxKind.EndOfFileToken) { expect(ast).toBe( @@ -184,7 +184,7 @@ describe('convert', () => { expect(maps.esTreeNodeToTSNodeMap.get(program.body[0])).toBeDefined(); expect(program.body[0]).not.toBe( - maps.tsNodeToESTreeNodeMap.get(ast.statements[0]), + maps.tsNodeToESTreeNodeMap.get(ast.statements[0] as any), ); checkMaps(ast); }); diff --git a/packages/typescript-estree/tests/lib/jsx.ts b/packages/typescript-estree/tests/lib/jsx.ts index 52b6debdf6b..a3e0148907c 100644 --- a/packages/typescript-estree/tests/lib/jsx.ts +++ b/packages/typescript-estree/tests/lib/jsx.ts @@ -23,11 +23,8 @@ describe('JSX', () => { /** * Test each fixture file */ - function testFixture( - fixturesDir: string, - useJSXTextNode: boolean, - ): (filename: string) => void { - return filename => { + function testFixture(fixturesDir: string, useJSXTextNode: boolean) { + return (filename: string): void => { const code = readFileSync(filename, 'utf8'); const config: TSESTreeOptions = { loc: true, diff --git a/packages/typescript-estree/tests/lib/semanticInfo.ts b/packages/typescript-estree/tests/lib/semanticInfo.ts index 7e5c634db9d..1afab0c5e44 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.ts @@ -280,7 +280,7 @@ describe('semanticInfo', () => { function testIsolatedFile( parseResult: ParseAndGenerateServicesResult, -) { +): void { // get type checker expect(parseResult).toHaveProperty('services.program.getTypeChecker'); const checker = parseResult.services.program!.getTypeChecker(); @@ -331,7 +331,7 @@ function testIsolatedFile( * @param {ts.TypeChecker} checker * @param {ts.Node} tsNode */ -function checkNumberArrayType(checker: ts.TypeChecker, tsNode: ts.Node) { +function checkNumberArrayType(checker: ts.TypeChecker, tsNode: ts.Node): void { const nodeType = checker.getTypeAtLocation(tsNode); expect(nodeType.flags).toBe(ts.TypeFlags.Object); expect((nodeType as ts.ObjectType).objectFlags).toBe( diff --git a/packages/typescript-estree/tools/test-utils.ts b/packages/typescript-estree/tools/test-utils.ts index 16210df104f..b9fcb51cab6 100644 --- a/packages/typescript-estree/tools/test-utils.ts +++ b/packages/typescript-estree/tools/test-utils.ts @@ -6,7 +6,7 @@ import { TSESTreeOptions } from '../src/parser-options'; * @param {Object} ast the AST object * @returns {Object} copy of the AST object */ -export function getRaw(ast: parser.TSESTree.Program) { +export function getRaw(ast: parser.TSESTree.Program): parser.TSESTree.Program { return JSON.parse( JSON.stringify(ast, (key, value) => { if ((key === 'start' || key === 'end') && typeof value === 'number') { @@ -20,7 +20,7 @@ export function getRaw(ast: parser.TSESTree.Program) { export function parseCodeAndGenerateServices( code: string, config: TSESTreeOptions, -) { +): parser.ParseAndGenerateServicesResult { return parser.parseAndGenerateServices(code, config); } @@ -36,18 +36,18 @@ export function createSnapshotTestBlock( code: string, config: TSESTreeOptions, generateServices?: true, -) { +): () => void { /** * @returns {Object} the AST object */ - function parse() { + function parse(): parser.TSESTree.Program { const ast = generateServices ? parser.parseAndGenerateServices(code, config).ast : parser.parse(code, config); return getRaw(ast); } - return () => { + return (): void => { try { const result = parse(); expect(result).toMatchSnapshot(); diff --git a/tests/integration/utils/jest-snapshot-resolver.js b/tests/integration/utils/jest-snapshot-resolver.js index 3032ef5d575..366a9611839 100644 --- a/tests/integration/utils/jest-snapshot-resolver.js +++ b/tests/integration/utils/jest-snapshot-resolver.js @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ /** * Use a jest snapshotResolver to map the test snapshot output back to the * linked volume. This means that even though we are running our tests inside diff --git a/tools/generate-contributors.ts b/tools/generate-contributors.ts index 34bf65ac52f..11b23765615 100644 --- a/tools/generate-contributors.ts +++ b/tools/generate-contributors.ts @@ -35,7 +35,7 @@ interface AllContributorsUser { contributions: string[]; } -async function* fetchUsers(page = 1) { +async function* fetchUsers(page = 1): AsyncIterableIterator { let lastLength = 0; do { const response = await fetch(`${contributorsApiUrl}&page=${page}`, { @@ -61,7 +61,7 @@ async function* fetchUsers(page = 1) { ); } -async function main() { +async function main(): Promise { const githubContributors: Contributor[] = []; // fetch all of the contributor info diff --git a/yarn.lock b/yarn.lock index 5924927ec6d..c86527946ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1428,6 +1428,11 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== +"@types/prettier@^1.18.0": + version "1.18.0" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.18.0.tgz#d2dbe4d5f76b455138f13a2d881278e2c06a733d" + integrity sha512-5N6WK/XXs9PLPpge2KOmOSaIym2vIo32GsrxM5YOFs7uZ8R9L/acg+hQzWsfwoHEpasqQkH0+3LzLTbiF1GFLQ== + "@types/semver@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6" @@ -6988,7 +6993,7 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prettier@^1.18.2: +prettier@*, prettier@^1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==