From 25401c96a8cdb218cf7c26330d3968bf7acf544c Mon Sep 17 00:00:00 2001 From: "Shahar \"Dawn\" Or" Date: Fri, 30 Jun 2023 12:33:39 +0700 Subject: [PATCH] fix: rules are at top level (not under overrides) BREAKING CHANGE: the rules are provided at the top level, instead of under an `overrides` property. Providing the rules under the `overrides` property was never a good idea. It prevents specifying which files the rules apply to (e.g. `[*.js, *.ts]`). I apologize. To migrate, make sure that your `extends` property is under an [`overrides` item][overrides]. An example is in the readme. To help verify your configuration, you could obtain a list of files that will be linted, this way: `DEBUG=eslint:cli-engine npx eslint `. [overrides]: https://eslint.org/docs/latest/use/configure/configuration-files#how-do-overrides-work closes #1149 closes #1088 Co-authored-by: Rostislav Simonik --- .eslintrc.json | 13 +- package.json | 2 +- readme.md | 18 +- src/index.test.ts | 470 ++++++++++++++++++++++------------------------ src/index.ts | 347 +++++++++++++++++----------------- tsconfig.json | 3 +- 6 files changed, 422 insertions(+), 431 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 54cf8a3e..49e2f6e0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,11 @@ { - "extends": "./lib/index.js", - "parserOptions": { - "project": "./tsconfig.json" - } + "overrides": [ + { + "files": ["*.js", "*.ts"], + "extends": "./lib/index.js", + "parserOptions": { + "project": "./tsconfig.json" + } + } + ] } diff --git a/package.json b/package.json index 7572d27a..09830177 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "scripts": { "compile": "tsc", - "lint": "eslint --ext .js,.ts .", + "lint": "eslint .", "editorconfig": "editorconfig-checker", "unit": "ava", "test": "run-s clean-artifacts editorconfig compile lint unit", diff --git a/readme.md b/readme.md index ecb7aafb..79b08bde 100644 --- a/readme.md +++ b/readme.md @@ -49,14 +49,20 @@ npm install --save-dev \ # Example config -Here is an example `.eslintrc.js`: +Here is an example `.eslintrc.js`. +Pay close attention to the `files` property, because it [determines which files are linted][specifying-target-files-to-lint]. ```js module.exports = { - extends: 'standard-with-typescript', - parserOptions: { - project: './tsconfig.json' - } + overrides: [ + { + files: ['*.js', '*.jsx', '*.ts', '*.tsx'], + extends: 'standard-with-typescript', + parserOptions: { + project: './tsconfig.json' + } + } + ], } ``` @@ -64,6 +70,8 @@ Note: Please read some important instructions regarding the `project` option [he There are [some more `parserOptions`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/README.md#configuration) you may care about. +[specifying-target-files-to-lint]: https://eslint.org/docs/latest/use/configure/configuration-files#specifying-target-files-to-lint + # Example command line usage: ``` diff --git a/src/index.test.ts b/src/index.test.ts index 29ac75f6..b84dfc39 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -40,9 +40,7 @@ const extractVersionSpec = (range: string): string => range.split('@').slice(-1) const equivalents = [...(new Linter()).getRules().keys()] .filter(name => Object.prototype.hasOwnProperty.call(typescriptEslintRules, name)) -if (exported.overrides === undefined) throw new Error('we seem to be exporting no overrides') -if (exported.overrides[0] === undefined) throw new Error('we seem to be exporting empty overrides') -const ourRules = exported.overrides[0].rules +const ourRules = exported.rules if (ourRules === undefined) throw new Error('we seem to be exporting no rules') const standardRules = configStandard.rules @@ -55,232 +53,227 @@ test('export', (t): void => { const expected: Linter.Config = { extends: 'eslint-config-standard', plugins: ['@typescript-eslint'], - overrides: [ - { - files: ['*.ts', '*.tsx'], - parser: '@typescript-eslint/parser', - rules: { - 'brace-style': 'off', - camelcase: 'off', - 'comma-dangle': 'off', - 'comma-spacing': 'off', - 'dot-notation': 'off', - 'func-call-spacing': 'off', - indent: 'off', - 'key-spacing': 'off', - 'keyword-spacing': 'off', - 'lines-between-class-members': 'off', - 'no-array-constructor': 'off', - 'no-dupe-class-members': 'off', - 'no-extra-parens': 'off', - 'no-loss-of-precision': 'off', - 'no-redeclare': 'off', - 'no-throw-literal': 'off', - 'no-undef': 'off', - 'no-unused-vars': 'off', - 'no-use-before-define': 'off', - 'no-unused-expressions': 'off', - 'no-useless-constructor': 'off', - 'no-void': ['error', { allowAsStatement: true }], - 'object-curly-spacing': 'off', - quotes: 'off', - semi: 'off', - 'space-before-blocks': 'off', - 'space-before-function-paren': 'off', - 'space-infix-ops': 'off', - '@typescript-eslint/adjacent-overload-signatures': 'error', - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/ban-ts-comment': ['error', { - 'ts-expect-error': 'allow-with-description', - 'ts-ignore': true, - 'ts-nocheck': true, - 'ts-check': false, - minimumDescriptionLength: 3 - }], - '@typescript-eslint/ban-tslint-comment': 'error', - '@typescript-eslint/ban-types': ['error', { - extendDefaults: false, - types: { - String: { - message: 'Use string instead', - fixWith: 'string' - }, - Boolean: { - message: 'Use boolean instead', - fixWith: 'boolean' - }, - Number: { - message: 'Use number instead', - fixWith: 'number' - }, - Symbol: { - message: 'Use symbol instead', - fixWith: 'symbol' - }, - BigInt: { - message: 'Use bigint instead', - fixWith: 'bigint' - }, - Function: { - message: [ - 'The `Function` type accepts any function-like value.', - 'It provides no type safety when calling the function, which can be a common source of bugs.', - 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', - 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.' - ].join('\n') - }, - // object typing - Object: { - message: [ - 'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', - '- If you want a type meaning "any object", you probably want `Record` instead.', - '- If you want a type meaning "any value", you probably want `unknown` instead.' - ].join('\n') - }, - '{}': { - message: [ - '`{}` actually means "any non-nullish value".', - '- If you want a type meaning "any object", you probably want `Record` instead.', - '- If you want a type meaning "any value", you probably want `unknown` instead.' - ].join('\n') - } - } - }], - '@typescript-eslint/brace-style': ['error', '1tbs', { allowSingleLine: true }], - '@typescript-eslint/class-literal-property-style': ['error', 'fields'], - '@typescript-eslint/comma-dangle': ['error', { - arrays: 'never', - objects: 'never', - imports: 'never', - exports: 'never', - functions: 'never', - enums: 'ignore', - generics: 'ignore', - tuples: 'ignore' - }], - '@typescript-eslint/comma-spacing': ['error', { before: false, after: true }], - '@typescript-eslint/consistent-generic-constructors': ['error', 'constructor'], - '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'], - '@typescript-eslint/consistent-type-assertions': [ - 'error', - { - assertionStyle: 'as', - objectLiteralTypeAssertions: 'never' - } - ], - '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], - '@typescript-eslint/consistent-type-exports': ['error', { - fixMixedExportsWithInlineTypeSpecifier: true - }], - '@typescript-eslint/consistent-type-imports': ['error', { - prefer: 'type-imports', - disallowTypeAnnotations: true, - fixStyle: 'inline-type-imports' - }], - '@typescript-eslint/dot-notation': ['error', { allowKeywords: true }], - '@typescript-eslint/explicit-function-return-type': ['error', { - allowExpressions: true, - allowHigherOrderFunctions: true, - allowTypedFunctionExpressions: true, - allowDirectConstAssertionInArrowFunctions: true - }], - '@typescript-eslint/func-call-spacing': ['error', 'never'], - '@typescript-eslint/indent': ['error', 2, { - SwitchCase: 1, - VariableDeclarator: 1, - outerIIFEBody: 1, - MemberExpression: 1, - FunctionDeclaration: { parameters: 1, body: 1 }, - FunctionExpression: { parameters: 1, body: 1 }, - CallExpression: { arguments: 1 }, - ArrayExpression: 1, - ObjectExpression: 1, - ImportDeclaration: 1, - flatTernaryExpressions: false, - ignoreComments: false, - ignoredNodes: ['TemplateLiteral *', 'JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXFragment', 'JSXOpeningFragment', 'JSXClosingFragment', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'], - offsetTernaryExpressions: true - }], - '@typescript-eslint/key-spacing': ['error', { beforeColon: false, afterColon: true }], - '@typescript-eslint/keyword-spacing': ['error', { before: true, after: true }], - '@typescript-eslint/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], - '@typescript-eslint/member-delimiter-style': [ - 'error', - { - multiline: { delimiter: 'none' }, - singleline: { delimiter: 'comma', requireLast: false } - } - ], - '@typescript-eslint/method-signature-style': 'error', - '@typescript-eslint/naming-convention': ['error', { - selector: 'variableLike', - leadingUnderscore: 'allow', - trailingUnderscore: 'allow', - format: ['camelCase', 'PascalCase', 'UPPER_CASE'] - }], - '@typescript-eslint/no-array-constructor': 'error', - '@typescript-eslint/no-base-to-string': 'error', - '@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: false, ignoreVoidOperator: false }], - '@typescript-eslint/no-dupe-class-members': 'error', - '@typescript-eslint/no-dynamic-delete': 'error', - '@typescript-eslint/no-empty-interface': ['error', { allowSingleExtends: true }], - '@typescript-eslint/no-extra-non-null-assertion': 'error', - '@typescript-eslint/no-extraneous-class': ['error', { allowWithDecorator: true }], - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-for-in-array': 'error', - '@typescript-eslint/no-implied-eval': 'error', - '@typescript-eslint/no-invalid-void-type': 'error', - '@typescript-eslint/no-loss-of-precision': 'error', - '@typescript-eslint/no-misused-new': 'error', - '@typescript-eslint/no-misused-promises': 'error', - '@typescript-eslint/no-namespace': 'error', - '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', - '@typescript-eslint/no-non-null-assertion': 'error', - '@typescript-eslint/no-this-alias': ['error', { allowDestructuring: true }], - '@typescript-eslint/no-extra-parens': ['error', 'functions'], - '@typescript-eslint/no-redeclare': ['error', { builtinGlobals: false }], - '@typescript-eslint/no-throw-literal': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unnecessary-type-constraint': 'error', - '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', - '@typescript-eslint/no-unused-vars': ['error', { args: 'none', caughtErrors: 'none', ignoreRestSiblings: true, vars: 'all' }], - '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: false, enums: false, variables: false, typedefs: false }], - '@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true, allowTaggedTemplates: true, allowTernary: true }], - '@typescript-eslint/no-useless-constructor': 'error', - '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/object-curly-spacing': ['error', 'always'], - '@typescript-eslint/prefer-function-type': 'error', - '@typescript-eslint/prefer-includes': 'error', - '@typescript-eslint/prefer-nullish-coalescing': ['error', { ignoreConditionalTests: false, ignoreMixedLogicalExpressions: false }], - '@typescript-eslint/prefer-optional-chain': 'error', - '@typescript-eslint/prefer-readonly': 'error', - '@typescript-eslint/prefer-reduce-type-parameter': 'error', - '@typescript-eslint/prefer-ts-expect-error': 'error', - '@typescript-eslint/promise-function-async': 'error', - '@typescript-eslint/quotes': ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }], - '@typescript-eslint/restrict-plus-operands': ['error', { checkCompoundAssignments: true }], - '@typescript-eslint/require-array-sort-compare': ['error', { ignoreStringArrays: true }], - '@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }], - '@typescript-eslint/return-await': ['error', 'always'], - '@typescript-eslint/semi': ['error', 'never'], - '@typescript-eslint/space-before-blocks': ['error', 'always'], - '@typescript-eslint/space-before-function-paren': ['error', 'always'], - '@typescript-eslint/space-infix-ops': 'error', - '@typescript-eslint/strict-boolean-expressions': ['error', { - allowString: false, - allowNumber: false, - allowNullableObject: false, - allowNullableBoolean: false, - allowNullableString: false, - allowNullableNumber: false, - allowAny: false - }], - '@typescript-eslint/triple-slash-reference': ['error', { lib: 'never', path: 'never', types: 'never' }], - '@typescript-eslint/type-annotation-spacing': 'error' + parser: '@typescript-eslint/parser', + rules: { + 'brace-style': 'off', + camelcase: 'off', + 'comma-dangle': 'off', + 'comma-spacing': 'off', + 'dot-notation': 'off', + 'func-call-spacing': 'off', + indent: 'off', + 'key-spacing': 'off', + 'keyword-spacing': 'off', + 'lines-between-class-members': 'off', + 'no-array-constructor': 'off', + 'no-dupe-class-members': 'off', + 'no-extra-parens': 'off', + 'no-loss-of-precision': 'off', + 'no-redeclare': 'off', + 'no-throw-literal': 'off', + 'no-undef': 'off', + 'no-unused-vars': 'off', + 'no-use-before-define': 'off', + 'no-unused-expressions': 'off', + 'no-useless-constructor': 'off', + 'no-void': ['error', { allowAsStatement: true }], + 'object-curly-spacing': 'off', + quotes: 'off', + semi: 'off', + 'space-before-blocks': 'off', + 'space-before-function-paren': 'off', + 'space-infix-ops': 'off', + '@typescript-eslint/adjacent-overload-signatures': 'error', + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/ban-ts-comment': ['error', { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': true, + 'ts-nocheck': true, + 'ts-check': false, + minimumDescriptionLength: 3 + }], + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/ban-types': ['error', { + extendDefaults: false, + types: { + String: { + message: 'Use string instead', + fixWith: 'string' + }, + Boolean: { + message: 'Use boolean instead', + fixWith: 'boolean' + }, + Number: { + message: 'Use number instead', + fixWith: 'number' + }, + Symbol: { + message: 'Use symbol instead', + fixWith: 'symbol' + }, + BigInt: { + message: 'Use bigint instead', + fixWith: 'bigint' + }, + Function: { + message: [ + 'The `Function` type accepts any function-like value.', + 'It provides no type safety when calling the function, which can be a common source of bugs.', + 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', + 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.' + ].join('\n') + }, + // object typing + Object: { + message: [ + 'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', + '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any value", you probably want `unknown` instead.' + ].join('\n') + }, + '{}': { + message: [ + '`{}` actually means "any non-nullish value".', + '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any value", you probably want `unknown` instead.' + ].join('\n') + } } - } - ] + }], + '@typescript-eslint/brace-style': ['error', '1tbs', { allowSingleLine: true }], + '@typescript-eslint/class-literal-property-style': ['error', 'fields'], + '@typescript-eslint/comma-dangle': ['error', { + arrays: 'never', + objects: 'never', + imports: 'never', + exports: 'never', + functions: 'never', + enums: 'ignore', + generics: 'ignore', + tuples: 'ignore' + }], + '@typescript-eslint/comma-spacing': ['error', { before: false, after: true }], + '@typescript-eslint/consistent-generic-constructors': ['error', 'constructor'], + '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'], + '@typescript-eslint/consistent-type-assertions': [ + 'error', + { + assertionStyle: 'as', + objectLiteralTypeAssertions: 'never' + } + ], + '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], + '@typescript-eslint/consistent-type-exports': ['error', { + fixMixedExportsWithInlineTypeSpecifier: true + }], + '@typescript-eslint/consistent-type-imports': ['error', { + prefer: 'type-imports', + disallowTypeAnnotations: true, + fixStyle: 'inline-type-imports' + }], + '@typescript-eslint/dot-notation': ['error', { allowKeywords: true }], + '@typescript-eslint/explicit-function-return-type': ['error', { + allowExpressions: true, + allowHigherOrderFunctions: true, + allowTypedFunctionExpressions: true, + allowDirectConstAssertionInArrowFunctions: true + }], + '@typescript-eslint/func-call-spacing': ['error', 'never'], + '@typescript-eslint/indent': ['error', 2, { + SwitchCase: 1, + VariableDeclarator: 1, + outerIIFEBody: 1, + MemberExpression: 1, + FunctionDeclaration: { parameters: 1, body: 1 }, + FunctionExpression: { parameters: 1, body: 1 }, + CallExpression: { arguments: 1 }, + ArrayExpression: 1, + ObjectExpression: 1, + ImportDeclaration: 1, + flatTernaryExpressions: false, + ignoreComments: false, + ignoredNodes: ['TemplateLiteral *', 'JSXElement', 'JSXElement > *', 'JSXAttribute', 'JSXIdentifier', 'JSXNamespacedName', 'JSXMemberExpression', 'JSXSpreadAttribute', 'JSXExpressionContainer', 'JSXOpeningElement', 'JSXClosingElement', 'JSXFragment', 'JSXOpeningFragment', 'JSXClosingFragment', 'JSXText', 'JSXEmptyExpression', 'JSXSpreadChild'], + offsetTernaryExpressions: true + }], + '@typescript-eslint/key-spacing': ['error', { beforeColon: false, afterColon: true }], + '@typescript-eslint/keyword-spacing': ['error', { before: true, after: true }], + '@typescript-eslint/lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], + '@typescript-eslint/member-delimiter-style': [ + 'error', + { + multiline: { delimiter: 'none' }, + singleline: { delimiter: 'comma', requireLast: false } + } + ], + '@typescript-eslint/method-signature-style': 'error', + '@typescript-eslint/naming-convention': ['error', { + selector: 'variableLike', + leadingUnderscore: 'allow', + trailingUnderscore: 'allow', + format: ['camelCase', 'PascalCase', 'UPPER_CASE'] + }], + '@typescript-eslint/no-array-constructor': 'error', + '@typescript-eslint/no-base-to-string': 'error', + '@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: false, ignoreVoidOperator: false }], + '@typescript-eslint/no-dupe-class-members': 'error', + '@typescript-eslint/no-dynamic-delete': 'error', + '@typescript-eslint/no-empty-interface': ['error', { allowSingleExtends: true }], + '@typescript-eslint/no-extra-non-null-assertion': 'error', + '@typescript-eslint/no-extraneous-class': ['error', { allowWithDecorator: true }], + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-for-in-array': 'error', + '@typescript-eslint/no-implied-eval': 'error', + '@typescript-eslint/no-invalid-void-type': 'error', + '@typescript-eslint/no-loss-of-precision': 'error', + '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-this-alias': ['error', { allowDestructuring: true }], + '@typescript-eslint/no-extra-parens': ['error', 'functions'], + '@typescript-eslint/no-redeclare': ['error', { builtinGlobals: false }], + '@typescript-eslint/no-throw-literal': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unnecessary-type-constraint': 'error', + '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', + '@typescript-eslint/no-unused-vars': ['error', { args: 'none', caughtErrors: 'none', ignoreRestSiblings: true, vars: 'all' }], + '@typescript-eslint/no-use-before-define': ['error', { functions: false, classes: false, enums: false, variables: false, typedefs: false }], + '@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true, allowTaggedTemplates: true, allowTernary: true }], + '@typescript-eslint/no-useless-constructor': 'error', + '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/object-curly-spacing': ['error', 'always'], + '@typescript-eslint/prefer-function-type': 'error', + '@typescript-eslint/prefer-includes': 'error', + '@typescript-eslint/prefer-nullish-coalescing': ['error', { ignoreConditionalTests: false, ignoreMixedLogicalExpressions: false }], + '@typescript-eslint/prefer-optional-chain': 'error', + '@typescript-eslint/prefer-readonly': 'error', + '@typescript-eslint/prefer-reduce-type-parameter': 'error', + '@typescript-eslint/prefer-ts-expect-error': 'error', + '@typescript-eslint/promise-function-async': 'error', + '@typescript-eslint/quotes': ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }], + '@typescript-eslint/restrict-plus-operands': ['error', { checkCompoundAssignments: true }], + '@typescript-eslint/require-array-sort-compare': ['error', { ignoreStringArrays: true }], + '@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }], + '@typescript-eslint/return-await': ['error', 'always'], + '@typescript-eslint/semi': ['error', 'never'], + '@typescript-eslint/space-before-blocks': ['error', 'always'], + '@typescript-eslint/space-before-function-paren': ['error', 'always'], + '@typescript-eslint/space-infix-ops': 'error', + '@typescript-eslint/strict-boolean-expressions': ['error', { + allowString: false, + allowNumber: false, + allowNullableObject: false, + allowNullableBoolean: false, + allowNullableString: false, + allowNullableNumber: false, + allowAny: false + }], + '@typescript-eslint/triple-slash-reference': ['error', { lib: 'never', path: 'never', types: 'never' }], + '@typescript-eslint/type-annotation-spacing': 'error' + } } t.deepEqual(exported, expected) @@ -358,15 +351,10 @@ test('devDep plugin range subset of dep parser range', async (t) => { }) test('Exported rule values do not reference eslint-config-standard ones', (t) => { - if (exported.overrides === undefined) throw new Error() - t.is(exported.overrides.length, 1) - const override = exported.overrides[0] - if (override.rules === undefined) throw new Error() - for (const ruleName in configStandard.rules) { if (typeof configStandard.rules[ruleName] !== 'object') continue // Non-objects use copy-by-value - t.false(override.rules[`@typescript-eslint/${ruleName}`] === configStandard.rules[ruleName]) + t.false(ourRules[`@typescript-eslint/${ruleName}`] === configStandard.rules[ruleName]) } }) @@ -522,22 +510,16 @@ test('our configuration is compatible with the plugin and parser at bottom of pe const config = structuredClone(exported) config.plugins = [typescriptEslintBottomPlugin] + config.parser = typescriptEslintBottomParser - if (config.overrides === undefined) throw new Error() - const overrides = config.overrides[0] - if (overrides === undefined) throw new Error() - - overrides.parser = typescriptEslintBottomParser - if (overrides.rules === undefined) throw new Error() - - overrides.rules = Object.fromEntries( - Object.entries(overrides.rules).map(([name, config]) => [ + config.rules = Object.fromEntries( + Object.entries(ourRules).map(([name, config]) => [ name.replace('@typescript-eslint/', `${typescriptEslintBottom}/`), config ]) ) - overrides.parserOptions = { + config.parserOptions = { project: './tsconfig.json' } diff --git a/src/index.ts b/src/index.ts index 08295267..d737851d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,187 +45,182 @@ function fromEntries (iterable: Array<[string, T]>): Record { const config: Linter.Config = { extends: 'eslint-config-standard', plugins: ['@typescript-eslint'], - overrides: [ - { - files: ['*.ts', '*.tsx'], - parser: '@typescript-eslint/parser', - rules: { - 'comma-dangle': 'off', + parser: '@typescript-eslint/parser', + rules: { + 'comma-dangle': 'off', - // TypeScript has this functionality by default: - 'no-undef': 'off', + // TypeScript has this functionality by default: + 'no-undef': 'off', - // Rules replaced by @typescript-eslint versions: - ...fromEntries(equivalents.map((name) => [name, 'off'])), - camelcase: 'off', - 'no-use-before-define': 'off', + // Rules replaced by @typescript-eslint versions: + ...fromEntries(equivalents.map((name) => [name, 'off'])), + camelcase: 'off', + 'no-use-before-define': 'off', - // @typescript-eslint versions of Standard.js rules: - ...fromEntries(equivalents.map((name) => [`@typescript-eslint/${name}`, ruleFromStandard(name)])), - '@typescript-eslint/no-use-before-define': ['error', { - functions: false, - classes: false, - enums: false, - variables: false, - typedefs: false // Only the TypeScript rule has this option. - }], + // @typescript-eslint versions of Standard.js rules: + ...fromEntries(equivalents.map((name) => [`@typescript-eslint/${name}`, ruleFromStandard(name)])), + '@typescript-eslint/no-use-before-define': ['error', { + functions: false, + classes: false, + enums: false, + variables: false, + typedefs: false // Only the TypeScript rule has this option. + }], - // Rules exclusive to Standard TypeScript: - '@typescript-eslint/adjacent-overload-signatures': 'error', - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/ban-ts-comment': ['error', { - 'ts-expect-error': 'allow-with-description', - 'ts-ignore': true, - 'ts-nocheck': true, - 'ts-check': false, - minimumDescriptionLength: 3 - }], - '@typescript-eslint/ban-tslint-comment': 'error', - '@typescript-eslint/ban-types': ['error', { - extendDefaults: false, - types: { - String: { - message: 'Use string instead', - fixWith: 'string' - }, - Boolean: { - message: 'Use boolean instead', - fixWith: 'boolean' - }, - Number: { - message: 'Use number instead', - fixWith: 'number' - }, - Symbol: { - message: 'Use symbol instead', - fixWith: 'symbol' - }, - BigInt: { - message: 'Use bigint instead', - fixWith: 'bigint' - }, - Function: { - message: [ - 'The `Function` type accepts any function-like value.', - 'It provides no type safety when calling the function, which can be a common source of bugs.', - 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', - 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.' - ].join('\n') - }, - // object typing - Object: { - message: [ - 'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', - '- If you want a type meaning "any object", you probably want `Record` instead.', - '- If you want a type meaning "any value", you probably want `unknown` instead.' - ].join('\n') - }, - '{}': { - message: [ - '`{}` actually means "any non-nullish value".', - '- If you want a type meaning "any object", you probably want `Record` instead.', - '- If you want a type meaning "any value", you probably want `unknown` instead.' - ].join('\n') - } - } - }], - '@typescript-eslint/class-literal-property-style': ['error', 'fields'], - '@typescript-eslint/comma-dangle': ['error', { - arrays: 'never', - objects: 'never', - imports: 'never', - exports: 'never', - functions: 'never', - enums: 'ignore', - generics: 'ignore', - tuples: 'ignore' - }], - '@typescript-eslint/consistent-generic-constructors': ['error', 'constructor'], - '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'], - '@typescript-eslint/consistent-type-assertions': [ - 'error', - { - assertionStyle: 'as', - objectLiteralTypeAssertions: 'never' - } - ], - '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], - '@typescript-eslint/consistent-type-exports': ['error', { - fixMixedExportsWithInlineTypeSpecifier: true - }], - '@typescript-eslint/consistent-type-imports': ['error', { - prefer: 'type-imports', - disallowTypeAnnotations: true, - fixStyle: 'inline-type-imports' - }], - '@typescript-eslint/explicit-function-return-type': ['error', { - allowExpressions: true, - allowHigherOrderFunctions: true, - allowTypedFunctionExpressions: true, - allowDirectConstAssertionInArrowFunctions: true - }], - '@typescript-eslint/member-delimiter-style': [ - 'error', - { - multiline: { delimiter: 'none' }, - singleline: { delimiter: 'comma', requireLast: false } - } - ], - '@typescript-eslint/method-signature-style': 'error', - '@typescript-eslint/naming-convention': ['error', { - selector: 'variableLike', - leadingUnderscore: 'allow', - trailingUnderscore: 'allow', - format: ['camelCase', 'PascalCase', 'UPPER_CASE'] - }], - '@typescript-eslint/no-base-to-string': 'error', - '@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: false, ignoreVoidOperator: false }], - '@typescript-eslint/no-dynamic-delete': 'error', - '@typescript-eslint/no-empty-interface': ['error', { allowSingleExtends: true }], - '@typescript-eslint/no-extra-non-null-assertion': 'error', - '@typescript-eslint/no-extraneous-class': ['error', { allowWithDecorator: true }], - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-for-in-array': 'error', - '@typescript-eslint/no-implied-eval': 'error', - '@typescript-eslint/no-invalid-void-type': 'error', - '@typescript-eslint/no-misused-new': 'error', - '@typescript-eslint/no-misused-promises': 'error', - '@typescript-eslint/no-namespace': 'error', - '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', - '@typescript-eslint/no-non-null-assertion': 'error', - '@typescript-eslint/no-this-alias': ['error', { allowDestructuring: true }], - '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unnecessary-type-constraint': 'error', - '@typescript-eslint/no-var-requires': 'error', - '@typescript-eslint/prefer-function-type': 'error', - '@typescript-eslint/prefer-includes': 'error', - '@typescript-eslint/prefer-nullish-coalescing': ['error', { ignoreConditionalTests: false, ignoreMixedLogicalExpressions: false }], - '@typescript-eslint/prefer-optional-chain': 'error', - '@typescript-eslint/prefer-readonly': 'error', - '@typescript-eslint/prefer-reduce-type-parameter': 'error', - '@typescript-eslint/prefer-ts-expect-error': 'error', - '@typescript-eslint/promise-function-async': 'error', - '@typescript-eslint/require-array-sort-compare': ['error', { ignoreStringArrays: true }], - '@typescript-eslint/restrict-plus-operands': ['error', { checkCompoundAssignments: true }], - '@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }], - '@typescript-eslint/return-await': ['error', 'always'], - '@typescript-eslint/strict-boolean-expressions': ['error', { - allowString: false, - allowNumber: false, - allowNullableObject: false, - allowNullableBoolean: false, - allowNullableString: false, - allowNullableNumber: false, - allowAny: false - }], - '@typescript-eslint/triple-slash-reference': ['error', { lib: 'never', path: 'never', types: 'never' }], - '@typescript-eslint/type-annotation-spacing': 'error', - 'no-void': ['error', { allowAsStatement: true }] + // Rules exclusive to Standard TypeScript: + '@typescript-eslint/adjacent-overload-signatures': 'error', + '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], + '@typescript-eslint/await-thenable': 'error', + '@typescript-eslint/ban-ts-comment': ['error', { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': true, + 'ts-nocheck': true, + 'ts-check': false, + minimumDescriptionLength: 3 + }], + '@typescript-eslint/ban-tslint-comment': 'error', + '@typescript-eslint/ban-types': ['error', { + extendDefaults: false, + types: { + String: { + message: 'Use string instead', + fixWith: 'string' + }, + Boolean: { + message: 'Use boolean instead', + fixWith: 'boolean' + }, + Number: { + message: 'Use number instead', + fixWith: 'number' + }, + Symbol: { + message: 'Use symbol instead', + fixWith: 'symbol' + }, + BigInt: { + message: 'Use bigint instead', + fixWith: 'bigint' + }, + Function: { + message: [ + 'The `Function` type accepts any function-like value.', + 'It provides no type safety when calling the function, which can be a common source of bugs.', + 'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', + 'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.' + ].join('\n') + }, + // object typing + Object: { + message: [ + 'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', + '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any value", you probably want `unknown` instead.' + ].join('\n') + }, + '{}': { + message: [ + '`{}` actually means "any non-nullish value".', + '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any value", you probably want `unknown` instead.' + ].join('\n') + } } - } - ] + }], + '@typescript-eslint/class-literal-property-style': ['error', 'fields'], + '@typescript-eslint/comma-dangle': ['error', { + arrays: 'never', + objects: 'never', + imports: 'never', + exports: 'never', + functions: 'never', + enums: 'ignore', + generics: 'ignore', + tuples: 'ignore' + }], + '@typescript-eslint/consistent-generic-constructors': ['error', 'constructor'], + '@typescript-eslint/consistent-indexed-object-style': ['error', 'record'], + '@typescript-eslint/consistent-type-assertions': [ + 'error', + { + assertionStyle: 'as', + objectLiteralTypeAssertions: 'never' + } + ], + '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], + '@typescript-eslint/consistent-type-exports': ['error', { + fixMixedExportsWithInlineTypeSpecifier: true + }], + '@typescript-eslint/consistent-type-imports': ['error', { + prefer: 'type-imports', + disallowTypeAnnotations: true, + fixStyle: 'inline-type-imports' + }], + '@typescript-eslint/explicit-function-return-type': ['error', { + allowExpressions: true, + allowHigherOrderFunctions: true, + allowTypedFunctionExpressions: true, + allowDirectConstAssertionInArrowFunctions: true + }], + '@typescript-eslint/member-delimiter-style': [ + 'error', + { + multiline: { delimiter: 'none' }, + singleline: { delimiter: 'comma', requireLast: false } + } + ], + '@typescript-eslint/method-signature-style': 'error', + '@typescript-eslint/naming-convention': ['error', { + selector: 'variableLike', + leadingUnderscore: 'allow', + trailingUnderscore: 'allow', + format: ['camelCase', 'PascalCase', 'UPPER_CASE'] + }], + '@typescript-eslint/no-base-to-string': 'error', + '@typescript-eslint/no-confusing-void-expression': ['error', { ignoreArrowShorthand: false, ignoreVoidOperator: false }], + '@typescript-eslint/no-dynamic-delete': 'error', + '@typescript-eslint/no-empty-interface': ['error', { allowSingleExtends: true }], + '@typescript-eslint/no-extra-non-null-assertion': 'error', + '@typescript-eslint/no-extraneous-class': ['error', { allowWithDecorator: true }], + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-for-in-array': 'error', + '@typescript-eslint/no-implied-eval': 'error', + '@typescript-eslint/no-invalid-void-type': 'error', + '@typescript-eslint/no-misused-new': 'error', + '@typescript-eslint/no-misused-promises': 'error', + '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-this-alias': ['error', { allowDestructuring: true }], + '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unnecessary-type-constraint': 'error', + '@typescript-eslint/no-var-requires': 'error', + '@typescript-eslint/prefer-function-type': 'error', + '@typescript-eslint/prefer-includes': 'error', + '@typescript-eslint/prefer-nullish-coalescing': ['error', { ignoreConditionalTests: false, ignoreMixedLogicalExpressions: false }], + '@typescript-eslint/prefer-optional-chain': 'error', + '@typescript-eslint/prefer-readonly': 'error', + '@typescript-eslint/prefer-reduce-type-parameter': 'error', + '@typescript-eslint/prefer-ts-expect-error': 'error', + '@typescript-eslint/promise-function-async': 'error', + '@typescript-eslint/require-array-sort-compare': ['error', { ignoreStringArrays: true }], + '@typescript-eslint/restrict-plus-operands': ['error', { checkCompoundAssignments: true }], + '@typescript-eslint/restrict-template-expressions': ['error', { allowNumber: true }], + '@typescript-eslint/return-await': ['error', 'always'], + '@typescript-eslint/strict-boolean-expressions': ['error', { + allowString: false, + allowNumber: false, + allowNullableObject: false, + allowNullableBoolean: false, + allowNullableString: false, + allowNullableNumber: false, + allowAny: false + }], + '@typescript-eslint/triple-slash-reference': ['error', { lib: 'never', path: 'never', types: 'never' }], + '@typescript-eslint/type-annotation-spacing': 'error', + 'no-void': ['error', { allowAsStatement: true }] + } } export = config diff --git a/tsconfig.json b/tsconfig.json index 54c0defa..47833c20 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "outDir": "lib" }, "include": [ - "src/**/*.ts" + "src/**/*.ts", + "commitlint.config.js" ] }