diff --git a/configs/js/docs/notes/duplicated-rules.md b/configs/js/docs/notes/duplicated-rules.md new file mode 100644 index 0000000..7276af0 --- /dev/null +++ b/configs/js/docs/notes/duplicated-rules.md @@ -0,0 +1,29 @@ +# Duplicated rules + +This is a list of rules that implements the same features and/or end +up fixing the same errors. + +- **[`@typescript/member-ordering`][ts/member-ordering], [`@typescript/sort-type-constituents`][ts/sort-type-constituents]**: + implements the same functions from [`eslint-plugin-perfectionist`][plugin-perfectionist] + +- **[`unicorn/no-for-loop`][un/no-for-loop] and [`@typescript/prefer-for-of`][ts/prefer-for-of]**: + `unicorn/no-for-loop` was used as it also reports when `i`/`index` is used. + +- **[`unicorn/prefer-includes`][un/prefer-includes] and [`@typescript/prefer-includes`][ts/prefer-includes]**: + `unicorn/prefer-includes` was used as it not needs type information to run. + +- **[`@typescript/prefer-regexp-exec`][ts/prefer-regexp-exec] and [`unicorn/prefer-regexp-test`][un/prefer-regexp-test]**: + `unicorn/prefer-regexp-exec` was used, because it reports on `RegExp#exec()` and `String#match()` + + +[ts/member-ordering]: +[ts/prefer-for-of]: +[ts/prefer-includes]: +[ts/prefer-regexp-exec]: +[ts/sort-type-constituents]: + +[un/no-for-loop]: +[un/prefer-includes]: +[un/prefer-regexp-test]: + +[plugin-perfectionist]: diff --git a/configs/js/src/configs/environments/node.js b/configs/js/src/configs/environments/node.js index 8dd2a8c..35564c9 100644 --- a/configs/js/src/configs/environments/node.js +++ b/configs/js/src/configs/environments/node.js @@ -5,6 +5,11 @@ import { jsFiles, tsFiles } from '../../constants.js'; const commonjs = { files: ['**/*.cts', '**/*.cjs'], rules: { + ...{}, // Plugin: @typescript-eslint/eslint-plugin + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-var-requires': 'off', + + ...{}, // Plugin: eslint-plugin-unicorn 'unicorn/prefer-module': 'off', }, }; diff --git a/configs/js/src/configs/index.d.ts b/configs/js/src/configs/index.d.ts index edab4e7..6e5c591 100644 --- a/configs/js/src/configs/index.d.ts +++ b/configs/js/src/configs/index.d.ts @@ -28,6 +28,10 @@ const configs: Readonly<{ recommended: Linter.FlatConfig strict: Linter.FlatConfig } + 'suggestions-typescript': { + recommended: Linter.FlatConfig + strict: Linter.FlatConfig + } }>; export default configs; diff --git a/configs/js/src/configs/index.js b/configs/js/src/configs/index.js index 50ccec0..80d34b8 100644 --- a/configs/js/src/configs/index.js +++ b/configs/js/src/configs/index.js @@ -1,7 +1,7 @@ +import typescript from './suggestions-typescript.js'; import environments from './environments/index.js'; import suggestions from './suggestions.js'; -import typescript from './typescript.js'; import formatting from './formatting.js'; import javascript from './javascript.js'; import overrides from './overrides.js'; @@ -16,6 +16,6 @@ const configs = { naming, overrides, suggestions, - typescript, + 'suggestions-typescript': typescript, }; export default configs; diff --git a/configs/js/src/configs/naming.js b/configs/js/src/configs/naming.js index a0c4c30..d93a15c 100644 --- a/configs/js/src/configs/naming.js +++ b/configs/js/src/configs/naming.js @@ -1,3 +1,4 @@ +/* eslint-disable unicorn/no-useless-spread */ import { jsFiles, tsFiles } from '../constants.js'; /** @@ -8,6 +9,7 @@ import { jsFiles, tsFiles } from '../constants.js'; const recommended = { files: [...tsFiles, ...jsFiles], rules: { + ...{}, // Plugin: eslint-plugin-unicorn 'unicorn/filename-case': ['error', { case: 'kebabCase' }], 'unicorn/prevent-abbreviations': 'error', }, @@ -22,7 +24,12 @@ const strict = { ...recommended, rules: { ...recommended.rules, + ...{}, // Plugin: @typescript-eslint/eslint-plugin + // '@typescript-eslint/naming-convention': 'error', + + ...{}, // Plugin: eslint-plugin-unicorn 'unicorn/no-keyword-prefix': 'error', + }, }; diff --git a/configs/js/src/configs/overrides.js b/configs/js/src/configs/overrides.js index 7fb685f..f65fae9 100644 --- a/configs/js/src/configs/overrides.js +++ b/configs/js/src/configs/overrides.js @@ -10,5 +10,15 @@ const performance = { }, }; -const overrides = { performance }; +/** @type {import('eslint').Linter.FlatConfig} */ +const inferrableTypes = { + files: [...tsFiles], + rules: { + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-inferrable-types': 'error', + '@typescript-eslint/typedef': 'off', + }, +}; + +const overrides = { inferrableTypes, performance }; export default overrides; diff --git a/configs/js/src/configs/suggestions-typescript.js b/configs/js/src/configs/suggestions-typescript.js new file mode 100644 index 0000000..0b6a715 --- /dev/null +++ b/configs/js/src/configs/suggestions-typescript.js @@ -0,0 +1,22 @@ + +import { tsFiles } from '../constants.js'; + +/** @type {import('eslint').Linter.FlatConfig} */ +const recommended = { + files: [...tsFiles], + rules: { + '@typescript-eslint/explicit-function-return-type': 'error', + }, +}; + +/** @type {import('eslint').Linter.FlatConfig} */ +const strict = { + ...recommended, + rules: { + ...recommended.rules, + '@typescript-eslint/explicit-member-accessibility': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'error', + }, +}; +const typescript = { recommended, strict }; +export default typescript; diff --git a/configs/js/src/configs/suggestions.js b/configs/js/src/configs/suggestions.js index 590923b..c913e21 100644 --- a/configs/js/src/configs/suggestions.js +++ b/configs/js/src/configs/suggestions.js @@ -32,6 +32,73 @@ const recommended = { 'quote-props': ['error', 'consistent-as-needed'], 'require-yield': 'error', + ...{}, // Plugin: @typescript-eslint/eslint-plugin + '@typescript-eslint/adjacent-overload-signatures': 'error', + '@typescript-eslint/array-type': 'error', + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/ban-ts-comment': 'error', + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/ban-types': 'error', + '@typescript-eslint/class-literal-property-style': 'error', + '@typescript-eslint/consistent-generic-constructors': 'error', + '@typescript-eslint/consistent-indexed-object-style': ['error', 'index-signature'], + '@typescript-eslint/consistent-type-assertions': 'error', + '@typescript-eslint/consistent-type-definitions': 'error', + '@typescript-eslint/no-base-to-string': 'error', + '@typescript-eslint/no-confusing-non-null-assertion': 'error', + '@typescript-eslint/no-confusing-void-expression': 'error', + '@typescript-eslint/no-duplicate-enum-values': 'error', + '@typescript-eslint/no-duplicate-type-constituents': 'error', + '@typescript-eslint/no-dynamic-delete': 'error', + '@typescript-eslint/no-empty-interface': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-extra-non-null-assertion': 'error', + '@typescript-eslint/no-extraneous-class': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-for-in-array': 'error', + '@typescript-eslint/no-import-type-side-effects': 'error', + '@typescript-eslint/no-invalid-void-type': 'error', + '@typescript-eslint/no-meaningless-void-operator': 'error', + '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-mixed-enums': 'error', + '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-redundant-type-constituents': 'error', + '@typescript-eslint/no-require-imports': 'error', + '@typescript-eslint/no-this-alias': 'error', + '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', + '@typescript-eslint/no-unnecessary-condition': 'error', + '@typescript-eslint/no-unnecessary-type-arguments': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unnecessary-type-constraint': 'error', + '@typescript-eslint/no-unsafe-argument': 'error', + '@typescript-eslint/no-unsafe-assignment': 'error', + '@typescript-eslint/no-unsafe-call': 'error', + '@typescript-eslint/no-unsafe-declaration-merging': 'error', + '@typescript-eslint/no-unsafe-enum-comparison': 'error', + '@typescript-eslint/no-unsafe-member-access': 'error', + '@typescript-eslint/no-unsafe-return': 'error', + '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/non-nullable-type-assertion-style': 'error', + '@typescript-eslint/prefer-as-const': 'error', + '@typescript-eslint/prefer-function-type': 'error', + '@typescript-eslint/prefer-literal-enum-member': 'error', + '@typescript-eslint/prefer-namespace-keyword': 'error', + '@typescript-eslint/prefer-nullish-coalescing': 'error', + '@typescript-eslint/prefer-optional-chain': 'error', + '@typescript-eslint/prefer-reduce-type-parameter': 'error', + '@typescript-eslint/prefer-return-this-type': 'error', + '@typescript-eslint/prefer-string-starts-ends-with': 'error', + '@typescript-eslint/prefer-ts-expect-error': 'error', + '@typescript-eslint/restrict-plus-operands': 'error', + '@typescript-eslint/restrict-template-expressions': 'error', + '@typescript-eslint/triple-slash-reference': 'error', + '@typescript-eslint/unbound-method': 'error', + '@typescript-eslint/unified-signatures': 'error', + ...{}, // Plugin: eslint-plugin-unicorn 'unicorn/better-regex': 'error', 'unicorn/catch-error-name': 'error', @@ -211,8 +278,11 @@ const strict = { ...{}, // Plugin: @typescript-eslint/eslint-plugin '@typescript-eslint/class-methods-use-this': 'error', + '@typescript-eslint/consistent-type-exports': ['error', { fixMixedExportsWithInlineTypeSpecifier: false }], + '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: true, fixStyle: 'separate-type-imports', prefer: 'type-imports' }], '@typescript-eslint/default-param-last': 'error', '@typescript-eslint/dot-notation': 'error', + '@typescript-eslint/method-signature-style': ['error', 'method'], '@typescript-eslint/no-array-constructor': 'error', '@typescript-eslint/no-empty-function': 'error', '@typescript-eslint/no-extra-semi': 'error', @@ -220,9 +290,19 @@ const strict = { '@typescript-eslint/no-loop-func': 'error', '@typescript-eslint/no-shadow': 'error', '@typescript-eslint/no-throw-literal': 'error', + '@typescript-eslint/no-unnecessary-qualifier': 'error', '@typescript-eslint/no-use-before-define': 'error', '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-useless-empty-export': 'error', + '@typescript-eslint/parameter-properties': 'error', + '@typescript-eslint/prefer-enum-initializers': 'error', + '@typescript-eslint/prefer-readonly': 'error', + '@typescript-eslint/prefer-readonly-parameter-types': 'error', + '@typescript-eslint/promise-function-async': 'error', + '@typescript-eslint/require-array-sort-compare': 'error', '@typescript-eslint/require-await': 'error', + '@typescript-eslint/switch-exhaustiveness-check': 'error', + '@typescript-eslint/typedef': 'error', // '@typescript-eslint/no-magic-numbers': ['error'], 'class-methods-use-this': 'off', 'default-param-last': 'off', diff --git a/configs/js/src/configs/typescript.js b/configs/js/src/configs/typescript.js deleted file mode 100644 index c203892..0000000 --- a/configs/js/src/configs/typescript.js +++ /dev/null @@ -1,41 +0,0 @@ - -import jsdocPlugin from 'eslint-plugin-jsdoc'; -import importPlugin from 'eslint-plugin-i'; -import { tsFiles } from '../constants.js'; - -/** @type {import('eslint').Linter.FlatConfig} */ -const recommended = { - files: [...tsFiles], - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - rules: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - ...jsdocPlugin.configs['recommended-typescript-error'].rules, - ...importPlugin.configs.typescript.rules, - - '@typescript-eslint/adjacent-overload-signatures': 'error', - '@typescript-eslint/array-type': 'error', - '@typescript-eslint/class-literal-property-style': 'error', - '@typescript-eslint/consistent-generic-constructors': 'error', - '@typescript-eslint/consistent-indexed-object-style': 'error', - '@typescript-eslint/consistent-type-assertions': 'error', - '@typescript-eslint/consistent-type-definitions': 'error', - '@typescript-eslint/consistent-type-exports': ['error'], - '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: true, prefer: 'type-imports' }], - '@typescript-eslint/explicit-function-return-type': 'error', - '@typescript-eslint/member-delimiter-style': ['error', { multiline: { delimiter: 'none' } }], - '@typescript-eslint/no-confusing-non-null-assertion': 'error', - '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-inferrable-types': 'error', - '@typescript-eslint/prefer-for-of': 'error', - '@typescript-eslint/prefer-function-type': 'error', - '@typescript-eslint/prefer-namespace-keyword': 'error', - '@typescript-eslint/type-annotation-spacing': 'error', - }, -}; - -/** @type {import('eslint').Linter.FlatConfig} */ -const strict = { - ...recommended, -}; -const typescript = { recommended, strict }; -export default typescript; diff --git a/configs/js/src/presets/recommended.js b/configs/js/src/presets/recommended.js index f5afa10..164dacb 100644 --- a/configs/js/src/presets/recommended.js +++ b/configs/js/src/presets/recommended.js @@ -6,8 +6,7 @@ const recommended = [ // TODO [>=1.0.0]: remove .javascript and .typescript configs // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access configs.javascript.recommended, - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - configs.typescript.recommended, + configs['suggestions-typescript'].recommended, configs.suggestions.recommended, configs.formatting.recommended, configs.naming.recommended, diff --git a/configs/js/src/presets/strict.js b/configs/js/src/presets/strict.js index edce7ac..945f2e2 100644 --- a/configs/js/src/presets/strict.js +++ b/configs/js/src/presets/strict.js @@ -6,8 +6,7 @@ const strict = [ // TODO [>=1.0.0]: remove .javascript and .typescript configs // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access configs.javascript.strict, - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - configs.typescript.strict, + configs['suggestions-typescript'].strict, configs.suggestions.strict, configs.formatting.strict, configs.naming.strict,