@mrpalmer/eslint-config 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,233 @@
1
+ import eslint from '@eslint/js'
2
+ import pluginImport from 'eslint-plugin-import'
3
+ import { config } from 'typescript-eslint'
4
+
5
+ export default config(
6
+ {
7
+ name: 'eslint/recommended',
8
+ ...eslint.configs.recommended,
9
+ },
10
+ {
11
+ name: 'mrpalmer/base',
12
+
13
+ linterOptions: {
14
+ reportUnusedDisableDirectives: 'error',
15
+ },
16
+ rules: {
17
+ 'accessor-pairs': 'error',
18
+ 'array-callback-return': 'error',
19
+ 'arrow-body-style': 'off',
20
+ 'block-scoped-var': 'error',
21
+ camelcase: 'off',
22
+ 'capitalized-comments': 'off',
23
+ 'class-methods-use-this': 'off',
24
+ complexity: ['error', 20],
25
+ 'consistent-return': 'error',
26
+ 'consistent-this': 'off',
27
+ curly: ['error', 'multi-line'],
28
+ 'default-case': 'error',
29
+ 'default-case-last': 'error',
30
+ 'default-param-last': 'off',
31
+ 'dot-notation': 'error',
32
+ eqeqeq: ['error', 'smart'],
33
+ 'func-name-matching': 'error',
34
+ 'func-names': 'error',
35
+ 'func-style': 'off',
36
+ 'grouped-accessor-pairs': 'off',
37
+ 'guard-for-in': 'error',
38
+ 'id-denylist': 'error',
39
+ 'id-length': 'off',
40
+ 'id-match': [
41
+ 'error',
42
+ // camelCase, PascalCase, __filename, CONST_VALUE, stream$, $el
43
+ '^\\$?(__)?(([A-Z]|[a-z]|[0-9]+)|([A-Z_]))*\\$?$',
44
+ ],
45
+ 'init-declarations': 'off',
46
+ 'logical-assignment-operators': [
47
+ 'warn',
48
+ 'always',
49
+ { enforceForIfStatements: true },
50
+ ],
51
+ 'max-classes-per-file': 'off',
52
+ 'max-depth': ['error', 4],
53
+ 'max-lines': [
54
+ 'error',
55
+ { max: 2500, skipBlankLines: false, skipComments: false },
56
+ ],
57
+ 'max-lines-per-function': 'off',
58
+ 'max-nested-callbacks': ['error', 7],
59
+ 'max-params': ['error', { max: 7 }],
60
+ 'max-statements': 'off',
61
+ 'new-cap': 'error',
62
+ 'no-alert': 'error',
63
+ 'no-array-constructor': 'error',
64
+ 'no-await-in-loop': 'error',
65
+ 'no-bitwise': 'error',
66
+ 'no-caller': 'error',
67
+ 'no-console': 'off',
68
+ 'no-constant-binary-expression': 'error',
69
+ 'no-constructor-return': 'error',
70
+ 'no-continue': 'off',
71
+ 'no-div-regex': 'error',
72
+ 'no-duplicate-imports': 'off',
73
+ 'no-else-return': 'off',
74
+ 'no-empty-function': 'off',
75
+ 'no-empty-static-block': 'warn',
76
+ 'no-eq-null': 'off',
77
+ 'no-eval': 'error',
78
+ 'no-extend-native': 'error',
79
+ 'no-extra-bind': 'error',
80
+ 'no-extra-label': 'error',
81
+ 'no-implicit-coercion': 'off',
82
+ 'no-implicit-globals': 'error',
83
+ 'no-implied-eval': 'error',
84
+ 'no-inline-comments': 'off',
85
+ 'no-inner-declarations': 'error',
86
+ 'no-invalid-this': 'error',
87
+ 'no-iterator': 'error',
88
+ 'no-label-var': 'error',
89
+ 'no-labels': 'error',
90
+ 'no-lone-blocks': 'error',
91
+ 'no-lonely-if': 'error',
92
+ 'no-loop-func': 'error',
93
+ 'no-magic-numbers': 'off',
94
+ 'no-multi-assign': 'error',
95
+ 'no-multi-str': 'error',
96
+ 'no-negated-condition': 'error',
97
+ 'no-nested-ternary': 'off',
98
+ 'no-new': 'error',
99
+ 'no-new-func': 'error',
100
+ 'no-new-native-nonconstructor': 'error',
101
+ 'no-new-wrappers': 'error',
102
+ 'no-object-constructor': 'error',
103
+ 'no-octal-escape': 'error',
104
+ 'no-param-reassign': 'off',
105
+ 'no-plusplus': 'off',
106
+ 'no-promise-executor-return': 'off',
107
+ 'no-proto': 'error',
108
+ 'no-restricted-exports': 'off',
109
+ 'no-restricted-globals': ['error', 'event', 'fdescribe'],
110
+ 'no-restricted-imports': 'off',
111
+ 'no-restricted-properties': 'off',
112
+ 'no-restricted-syntax': ['error', 'WithStatement'],
113
+ 'no-return-assign': 'error',
114
+ 'no-script-url': 'error',
115
+ 'no-self-compare': 'error',
116
+ 'no-sequences': 'error',
117
+ 'no-shadow': 'off',
118
+ 'no-template-curly-in-string': 'error',
119
+ 'no-ternary': 'off',
120
+ 'no-throw-literal': 'error',
121
+ 'no-undef-init': 'error',
122
+ 'no-undefined': 'off',
123
+ 'no-underscore-dangle': 'off',
124
+ 'no-unmodified-loop-condition': 'error',
125
+ 'no-unneeded-ternary': 'error',
126
+ 'no-unreachable-loop': 'error',
127
+ 'no-unused-expressions': 'off',
128
+ 'no-unused-private-class-members': 'error',
129
+ 'no-unused-vars': [
130
+ 'error',
131
+ {
132
+ args: 'after-used',
133
+ argsIgnorePattern: '^_',
134
+ ignoreRestSiblings: true,
135
+ varsIgnorePattern: '^ignored',
136
+ },
137
+ ],
138
+ 'no-use-before-define': ['error', 'nofunc'],
139
+ 'no-useless-assignment': 'warn',
140
+ 'no-useless-call': 'error',
141
+ 'no-useless-computed-key': 'error',
142
+ 'no-useless-concat': 'error',
143
+ 'no-useless-constructor': 'error',
144
+ 'no-useless-rename': 'error',
145
+ 'no-useless-return': 'error',
146
+ 'no-var': 'error',
147
+ 'no-void': 'off',
148
+ 'no-warning-comments': [
149
+ 'error',
150
+ { location: 'anywhere', terms: ['fixme'] },
151
+ ],
152
+ 'object-shorthand': ['error', 'properties'],
153
+ 'one-var': ['error', { initialized: 'never', uninitialized: 'always' }],
154
+ 'operator-assignment': 'off',
155
+ 'prefer-arrow-callback': [
156
+ 'error',
157
+ { allowNamedFunctions: true, allowUnboundThis: true },
158
+ ],
159
+ 'prefer-const': 'error',
160
+ 'prefer-destructuring': 'off',
161
+ 'prefer-exponentiation-operator': 'warn',
162
+ 'prefer-named-capture-group': 'off',
163
+ 'prefer-numeric-literals': 'error',
164
+ 'prefer-object-has-own': 'error',
165
+ 'prefer-object-spread': 'warn',
166
+ 'prefer-promise-reject-errors': 'off',
167
+ 'prefer-regex-literals': 'off',
168
+ 'prefer-rest-params': 'error',
169
+ 'prefer-spread': 'error',
170
+ 'prefer-template': 'error',
171
+ radix: 'error',
172
+ 'require-atomic-updates': 'off',
173
+ 'require-await': 'off',
174
+ 'require-unicode-regexp': 'off',
175
+ 'sort-imports': 'off',
176
+ 'sort-keys': 'off',
177
+ 'sort-vars': 'off',
178
+ strict: 'error',
179
+ 'symbol-description': 'error',
180
+ 'unicode-bom': ['error', 'never'],
181
+ 'vars-on-top': 'error',
182
+ yoda: 'error',
183
+ },
184
+ },
185
+ pluginImport.flatConfigs.recommended,
186
+ {
187
+ name: 'mrpalmer/import',
188
+ rules: {
189
+ 'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
190
+ 'import/dynamic-import-chunkname': 'off',
191
+ 'import/exports-last': 'off',
192
+ 'import/extensions': 'off',
193
+ 'import/first': 'error',
194
+ 'import/group-exports': 'off',
195
+ 'import/max-dependencies': 'off',
196
+ 'import/newline-after-import': 'off',
197
+ 'import/no-absolute-path': 'error',
198
+ 'import/no-amd': 'error',
199
+ 'import/no-anonymous-default-export': [
200
+ 'error',
201
+ { allowArray: true, allowObject: true },
202
+ ],
203
+ 'import/no-commonjs': 'off',
204
+ 'import/no-cycle': 'off',
205
+ 'import/no-default-export': 'off',
206
+ 'import/no-deprecated': 'warn',
207
+ 'import/no-dynamic-require': 'off',
208
+ 'import/no-empty-named-blocks': 'warn',
209
+ 'import/no-extraneous-dependencies': 'error',
210
+ 'import/no-import-module-exports': 'error',
211
+ 'import/no-internal-modules': 'off',
212
+ 'import/no-mutable-exports': 'error',
213
+ 'import/no-named-default': 'error',
214
+ 'import/no-named-export': 'off',
215
+ 'import/no-namespace': 'off',
216
+ 'import/no-nodejs-modules': 'off',
217
+ 'import/no-relative-packages': 'warn',
218
+ 'import/no-relative-parent-imports': 'off',
219
+ 'import/no-restricted-paths': 'off',
220
+ 'import/no-self-import': 'error',
221
+ 'import/no-unassigned-import': 'off',
222
+ 'import/no-unused-modules': 'off',
223
+ 'import/no-useless-path-segments': 'error',
224
+ 'import/no-webpack-loader-syntax': 'error',
225
+ 'import/order': 'off',
226
+ 'import/prefer-default-export': 'off',
227
+ 'import/unambiguous': 'off',
228
+ },
229
+ settings: {
230
+ 'import/ignore': ['node_modules', '.json$', '.(scss|less|css|styl)$'],
231
+ },
232
+ }
233
+ )
@@ -0,0 +1,101 @@
1
+ import pluginJest from 'eslint-plugin-jest'
2
+ import pluginJestDom from 'eslint-plugin-jest-dom'
3
+ import pluginTestingLibrary from 'eslint-plugin-testing-library'
4
+ import tseslint from 'typescript-eslint'
5
+ import { getAllDependencies } from '../utils/packageJson.js'
6
+
7
+ const allDeps = new Set(Object.keys(getAllDependencies()))
8
+
9
+ const hasJestDom = allDeps.has('@testing-library/jest-dom')
10
+ const hasTestingLibraryDom = allDeps.has('@testing-library/dom')
11
+ const hasTestingLibraryReact = allDeps.has('@testing-library/react')
12
+ const hasTestingLibrary = hasTestingLibraryDom || hasTestingLibraryReact
13
+
14
+ export default tseslint.config(
15
+ {
16
+ extends: [
17
+ { name: 'jest/recommended', ...pluginJest.configs['flat/recommended'] },
18
+ { name: 'jest/style', ...pluginJest.configs['flat/style'] },
19
+ hasJestDom && {
20
+ name: 'jest-dom/recommended',
21
+ ...pluginJestDom.configs['flat/recommended'],
22
+ },
23
+ hasTestingLibraryReact
24
+ ? {
25
+ name: 'testing-library/react',
26
+ ...pluginTestingLibrary.configs['flat/react'],
27
+ }
28
+ : hasTestingLibraryDom
29
+ ? {
30
+ name: 'testing-library/dom',
31
+ ...pluginTestingLibrary.configs['flat/dom'],
32
+ }
33
+ : null,
34
+ ].filter(Boolean),
35
+ files: ['**/__tests__/**/*.+(js|ts)?(x)', '**/*.{spec,test}.+(js|ts)?(x)'],
36
+ name: 'mrpalmer/jest',
37
+
38
+ rules: {
39
+ 'react/display-name': 'off', // we don't need a display name in test files
40
+
41
+ 'jest/consistent-test-it': 'off',
42
+ 'jest/max-expects': 'off',
43
+ 'jest/max-nested-describe': 'error',
44
+ 'jest/no-conditional-in-test': 'error',
45
+ 'jest/no-confusing-set-timeout': 'error',
46
+ 'jest/no-duplicate-hooks': 'off',
47
+ 'jest/no-hooks': 'off',
48
+ 'jest/no-large-snapshots': ['warn', { maxSize: 300 }],
49
+ 'jest/no-restricted-jest-methods': 'off',
50
+ 'jest/no-restricted-matchers': 'off',
51
+ 'jest/no-test-return-statement': 'off',
52
+ 'jest/no-untyped-mock-factory': 'error',
53
+ 'jest/padding-around-after-all-blocks': 'off',
54
+ 'jest/padding-around-after-each-blocks': 'off',
55
+ 'jest/padding-around-all': 'off',
56
+ 'jest/padding-around-before-all-blocks': 'off',
57
+ 'jest/padding-around-before-each-blocks': 'off',
58
+ 'jest/padding-around-describe-blocks': 'off',
59
+ 'jest/padding-around-expect-groups': 'off',
60
+ 'jest/padding-around-test-blocks': 'off',
61
+ 'jest/prefer-called-with': 'error',
62
+ 'jest/prefer-comparison-matcher': 'warn',
63
+ 'jest/prefer-each': 'warn',
64
+ 'jest/prefer-equality-matcher': 'warn',
65
+ 'jest/prefer-expect-assertions': 'off',
66
+ 'jest/prefer-expect-resolves': 'off',
67
+ 'jest/prefer-hooks-in-order': 'error',
68
+ 'jest/prefer-hooks-on-top': 'error',
69
+ 'jest/prefer-importing-jest-globals': 'off',
70
+ 'jest/prefer-jest-mocked': 'warn',
71
+ 'jest/prefer-lowercase-title': 'off',
72
+ 'jest/prefer-mock-promise-shorthand': 'warn',
73
+ 'jest/prefer-snapshot-hint': ['error', 'multi'],
74
+ 'jest/prefer-spy-on': 'off',
75
+ 'jest/prefer-strict-equal': 'off',
76
+ 'jest/prefer-todo': 'warn',
77
+ 'jest/require-hook': 'off',
78
+ 'jest/require-to-throw-message': 'off',
79
+ 'jest/require-top-level-describe': 'off',
80
+ 'jest/unbound-method': 'off',
81
+
82
+ ...(hasTestingLibrary
83
+ ? {
84
+ 'testing-library/consistent-data-testid': 'off',
85
+ 'testing-library/prefer-explicit-assert': 'warn',
86
+ 'testing-library/prefer-implicit-assert': 'off',
87
+ 'testing-library/prefer-query-matchers': 'off',
88
+ 'testing-library/prefer-user-event': 'error',
89
+ }
90
+ : null),
91
+ },
92
+ },
93
+ {
94
+ files: ['**/__tests__/**/*.ts?(x)', '**/*.{spec,test}.ts?(x)'],
95
+ name: 'mrpalmer/jest/typescript',
96
+ rules: {
97
+ '@typescript-eslint/unbound-method': 'off',
98
+ 'jest/unbound-method': 'error',
99
+ },
100
+ }
101
+ )
@@ -0,0 +1,154 @@
1
+ import pluginJsxA11y from 'eslint-plugin-jsx-a11y'
2
+ import pluginReact from 'eslint-plugin-react'
3
+ import pluginReactHooks from 'eslint-plugin-react-hooks'
4
+ import globals from 'globals'
5
+ import tseslint from 'typescript-eslint'
6
+ import {
7
+ getAllDependencies,
8
+ getMinimumSupportedVersion,
9
+ } from '../utils/packageJson.js'
10
+
11
+ const oldestSupportedReactVersion = '16.5.2'
12
+
13
+ const allDeps = getAllDependencies()
14
+ const minimumSupportedReactVersion =
15
+ getMinimumSupportedVersion(allDeps, 'react') ?? oldestSupportedReactVersion
16
+ const hasPropTypes = Object.hasOwn(allDeps, 'prop-types')
17
+
18
+ // jsx-a11y/label-has-for is deprecated but still defined in the recommended config
19
+ delete pluginJsxA11y.flatConfigs.recommended.rules['jsx-a11y/label-has-for']
20
+
21
+ export default tseslint.config(
22
+ {
23
+ extends: [
24
+ {
25
+ name: 'react/recommended',
26
+ ...pluginReact.configs.flat.recommended,
27
+ },
28
+ pluginJsxA11y.flatConfigs.recommended,
29
+ {
30
+ name: 'react-hooks/recommended',
31
+ plugins: {
32
+ 'react-hooks': pluginReactHooks,
33
+ },
34
+ rules: pluginReactHooks.configs.recommended.rules,
35
+ },
36
+ ],
37
+ files: ['**/*.{js,jsx,ts,tsx}'],
38
+ languageOptions: {
39
+ globals: {
40
+ ...globals.browser,
41
+ },
42
+ },
43
+ name: 'mrpalmer/react',
44
+ rules: {
45
+ 'react/boolean-prop-naming': 'off',
46
+ 'react/button-has-type': 'off',
47
+ 'react/checked-requires-onchange-or-readonly': 'error',
48
+ 'react/default-props-match-prop-types': hasPropTypes ? 'error' : 'off',
49
+ 'react/destructuring-assignment': 'off',
50
+ 'react/forbid-component-props': 'off',
51
+ 'react/forbid-dom-props': 'off',
52
+ 'react/forbid-elements': 'off',
53
+ 'react/forbid-foreign-prop-types': hasPropTypes ? 'error' : 'off',
54
+ 'react/forbid-prop-types': 'off',
55
+ 'react/forward-ref-uses-ref': 'error',
56
+ 'react/function-component-definition': 'off',
57
+ 'react/hook-use-state': 'off',
58
+ 'react/iframe-missing-sandbox': 'warn',
59
+ 'react/jsx-boolean-value': 'off',
60
+ 'react/jsx-child-element-spacing': 'warn',
61
+ 'react/jsx-closing-bracket-location': 'off',
62
+ 'react/jsx-closing-tag-location': 'off',
63
+ 'react/jsx-curly-brace-presence': [
64
+ 'warn',
65
+ { children: 'ignore', propElementValues: 'always', props: 'never' },
66
+ ],
67
+ 'react/jsx-curly-newline': 'off',
68
+ 'react/jsx-curly-spacing': 'off',
69
+ 'react/jsx-equals-spacing': 'off',
70
+ 'react/jsx-filename-extension': ['error', { extensions: ['.js'] }],
71
+ 'react/jsx-first-prop-new-line': 'off',
72
+ 'react/jsx-fragments': 'off',
73
+ 'react/jsx-handler-names': 'off',
74
+ 'react/jsx-indent': 'off',
75
+ 'react/jsx-indent-props': 'off',
76
+ 'react/jsx-max-depth': 'off',
77
+ 'react/jsx-max-props-per-line': 'off',
78
+ 'react/jsx-newline': 'off',
79
+ 'react/jsx-no-bind': 'off',
80
+ 'react/jsx-no-constructed-context-values': 'off',
81
+ 'react/jsx-no-leaked-render': 'off',
82
+ 'react/jsx-no-literals': 'off',
83
+ 'react/jsx-no-script-url': 'error',
84
+ 'react/jsx-no-useless-fragment': 'warn',
85
+ 'react/jsx-one-expression-per-line': 'off',
86
+ 'react/jsx-pascal-case': 'error',
87
+ 'react/jsx-props-no-multi-spaces': 'off',
88
+ 'react/jsx-props-no-spread-multi': 'warn',
89
+ 'react/jsx-props-no-spreading': 'off',
90
+ 'react/jsx-sort-props': 'off',
91
+ 'react/jsx-tag-spacing': 'off',
92
+ 'react/jsx-wrap-multilines': 'off',
93
+ 'react/no-access-state-in-setstate': 'error',
94
+ 'react/no-adjacent-inline-elements': 'off',
95
+ 'react/no-array-index-key': 'off', // sometimes you don't care about the issues, or they don't apply
96
+ 'react/no-arrow-function-lifecycle': 'error',
97
+ 'react/no-danger': 'off',
98
+ 'react/no-did-mount-set-state': 'error',
99
+ 'react/no-did-update-set-state': 'error',
100
+ 'react/no-invalid-html-attribute': 'error',
101
+ 'react/no-multi-comp': 'off',
102
+ 'react/no-namespace': 'error',
103
+ 'react/no-object-type-as-default-prop': 'warn',
104
+ 'react/no-redundant-should-component-update': 'error',
105
+ 'react/no-set-state': 'off',
106
+ 'react/no-this-in-sfc': 'error',
107
+ 'react/no-typos': 'error',
108
+ 'react/no-unescaped-entities': 'warn',
109
+ 'react/no-unsafe': 'warn', // if you need it there should be a comment explaining why
110
+ 'react/no-unstable-nested-components': ['error', { allowAsProps: true }],
111
+ 'react/no-unused-class-component-methods': 'error',
112
+ 'react/no-unused-prop-types': hasPropTypes ? 'error' : 'off',
113
+ 'react/no-unused-state': 'error',
114
+ 'react/no-will-update-set-state': 'error',
115
+ 'react/prefer-es6-class': 'off',
116
+ 'react/prefer-exact-props': 'off',
117
+ 'react/prefer-read-only-props': 'off',
118
+ 'react/prefer-stateless-function': 'off',
119
+ 'react/prop-types': hasPropTypes ? 'error' : 'off',
120
+ 'react/require-default-props': 'off', // sometimes the default value is undefined so that's fine...
121
+ 'react/require-optimization': 'off',
122
+ 'react/self-closing-comp': 'error',
123
+ 'react/sort-comp': 'off',
124
+ 'react/sort-default-props': 'off',
125
+ 'react/sort-prop-types': 'off',
126
+ 'react/state-in-constructor': 'off',
127
+ 'react/static-property-placement': 'off',
128
+ 'react/style-prop-object': 'error',
129
+ 'react/void-dom-elements-no-children': 'error',
130
+
131
+ 'jsx-a11y/lang': 'error',
132
+ 'jsx-a11y/no-aria-hidden-on-focusable': 'off',
133
+ 'jsx-a11y/no-autofocus': 'off',
134
+ 'jsx-a11y/prefer-tag-over-role': 'off',
135
+ 'jsx-a11y/tabindex-no-positive': 'warn',
136
+ },
137
+ settings: {
138
+ react: {
139
+ version: minimumSupportedReactVersion,
140
+ },
141
+ },
142
+ },
143
+ {
144
+ files: ['**/*.ts?(x)'],
145
+ name: 'mrpalmer/react/typescript',
146
+ rules: {
147
+ 'react/jsx-filename-extension': [
148
+ 'error',
149
+ { extensions: ['.ts', '.tsx'] },
150
+ ],
151
+ 'react/prop-types': 'off',
152
+ },
153
+ }
154
+ )
@@ -0,0 +1,150 @@
1
+ import pluginImport from 'eslint-plugin-import'
2
+ import tseslint from 'typescript-eslint'
3
+
4
+ // typescript-eslint still enables a couple of base rules that are deprecated in v9
5
+ function disableDeprecatedRules(config) {
6
+ if (!config.rules) return
7
+ delete config.rules['no-new-symbol']
8
+ delete config.rules['no-return-await']
9
+ }
10
+ tseslint.configs.strictTypeChecked.forEach(disableDeprecatedRules)
11
+ tseslint.configs.stylisticTypeChecked.forEach(disableDeprecatedRules)
12
+
13
+ export default tseslint.config({
14
+ extends: [
15
+ ...tseslint.configs.strictTypeChecked,
16
+ ...tseslint.configs.stylisticTypeChecked,
17
+ pluginImport.configs.typescript,
18
+ ],
19
+ files: ['**/*.ts?(x)'],
20
+ languageOptions: {
21
+ parserOptions: {
22
+ projectService: true,
23
+ },
24
+ },
25
+ name: 'mrpalmer/typescript',
26
+ rules: {
27
+ 'import/consistent-type-specifier-style': 'off',
28
+ 'import/no-unresolved': 'off', // ts(2307)
29
+
30
+ 'constructor-super': 'off', // ts(2335) & ts(2377)
31
+ 'getter-return': 'off', // ts(2378)
32
+ 'no-const-assign': 'off', // ts(2588)
33
+ 'no-dupe-args': 'off', // ts(2300)
34
+ 'no-dupe-keys': 'off', // ts(1117)
35
+ 'no-func-assign': 'off', // ts(2539)
36
+ 'no-import-assign': 'off', // ts(2539) & ts(2540)
37
+ 'no-obj-calls': 'off', // ts(2349)
38
+ 'no-setter-return': 'off', // ts(2408)
39
+ 'no-this-before-super': 'off', // ts(2376)
40
+ 'no-undef': 'off', // ts(2304)
41
+ 'no-unreachable': 'off', // ts(7027)
42
+ 'no-unsafe-negation': 'off', // ts(2365) & ts(2360) & ts(2358)
43
+ 'valid-typeof': 'off', // ts(2367)
44
+
45
+ 'no-var': 'error', // TS transpiles let/const to var, so no need for vars anymore
46
+ 'prefer-const': 'error', // TS provides better types with const
47
+ 'prefer-rest-params': 'error', // TS provides better types with rest args over arguments
48
+ 'prefer-spread': 'error', // TS transpiles spread to apply, so no need for manual apply
49
+
50
+ '@typescript-eslint/consistent-return': 'error',
51
+ 'consistent-return': 'off',
52
+
53
+ '@typescript-eslint/default-param-last': 'off',
54
+ 'default-param-last': 'off',
55
+
56
+ '@typescript-eslint/init-declarations': 'off',
57
+ 'init-declarations': 'off',
58
+
59
+ '@typescript-eslint/max-params': ['error', { max: 7 }],
60
+ 'max-params': 'off',
61
+
62
+ '@typescript-eslint/no-dupe-class-members': 'off', // ts(2393) & ts(2300)
63
+ 'no-dupe-class-members': 'off',
64
+
65
+ '@typescript-eslint/no-empty-function': 'off',
66
+ 'no-empty-function': 'off',
67
+
68
+ '@typescript-eslint/no-invalid-this': 'error',
69
+ 'no-invalid-this': 'off',
70
+
71
+ '@typescript-eslint/no-loop-func': 'error',
72
+ 'no-loop-func': 'off',
73
+
74
+ '@typescript-eslint/no-magic-numbers': 'off',
75
+ 'no-magic-numbers': 'off',
76
+
77
+ '@typescript-eslint/no-redeclare': 'off', // ts(2451)
78
+ 'no-redeclare': 'off',
79
+
80
+ '@typescript-eslint/no-shadow': 'off',
81
+ 'no-shadow': 'off',
82
+
83
+ '@typescript-eslint/no-unused-expressions': 'off',
84
+ 'no-unused-expressions': 'off',
85
+
86
+ '@typescript-eslint/no-unused-vars': [
87
+ 'error',
88
+ {
89
+ args: 'after-used',
90
+ argsIgnorePattern: '^_',
91
+ ignoreRestSiblings: true,
92
+ varsIgnorePattern: '^ignored',
93
+ },
94
+ ],
95
+ 'no-unused-vars': 'off',
96
+
97
+ '@typescript-eslint/no-use-before-define': ['error', 'nofunc'],
98
+ 'no-use-before-define': 'off',
99
+
100
+ '@typescript-eslint/array-type': ['error', { default: 'array-simple' }],
101
+ '@typescript-eslint/class-methods-use-this': 'off',
102
+ '@typescript-eslint/consistent-type-exports': [
103
+ 'error',
104
+ { fixMixedExportsWithInlineTypeSpecifier: true },
105
+ ],
106
+ '@typescript-eslint/consistent-type-imports': [
107
+ 'error',
108
+ { fixStyle: 'inline-type-imports' },
109
+ ],
110
+ '@typescript-eslint/explicit-function-return-type': 'off',
111
+ '@typescript-eslint/explicit-member-accessibility': 'off',
112
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
113
+ '@typescript-eslint/member-ordering': 'off',
114
+ '@typescript-eslint/method-signature-style': 'off',
115
+ '@typescript-eslint/naming-convention': 'off',
116
+ '@typescript-eslint/no-base-to-string': 'warn',
117
+ '@typescript-eslint/no-confusing-void-expression': [
118
+ 'warn',
119
+ { ignoreArrowShorthand: true, ignoreVoidOperator: true },
120
+ ],
121
+ '@typescript-eslint/no-floating-promises': 'warn',
122
+ '@typescript-eslint/no-import-type-side-effects': 'error',
123
+ '@typescript-eslint/no-inferrable-types': 'warn',
124
+ '@typescript-eslint/no-restricted-imports': 'off',
125
+ '@typescript-eslint/no-restricted-types': 'off',
126
+ '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn',
127
+ '@typescript-eslint/no-unnecessary-parameter-property-assignment': 'warn',
128
+ '@typescript-eslint/no-unnecessary-qualifier': 'warn',
129
+ '@typescript-eslint/no-unnecessary-type-arguments': 'warn',
130
+ '@typescript-eslint/no-unsafe-type-assertion': 'error',
131
+ '@typescript-eslint/no-useless-empty-export': 'error',
132
+ '@typescript-eslint/parameter-properties': [
133
+ 'error',
134
+ { prefer: 'parameter-property' },
135
+ ],
136
+ '@typescript-eslint/prefer-destructuring': 'off',
137
+ '@typescript-eslint/prefer-enum-initializers': 'error',
138
+ '@typescript-eslint/prefer-readonly': 'off',
139
+ '@typescript-eslint/prefer-readonly-parameter-types': 'off',
140
+ '@typescript-eslint/promise-function-async': 'off',
141
+ '@typescript-eslint/require-array-sort-compare': 'off',
142
+ '@typescript-eslint/restrict-template-expressions': [
143
+ 'error',
144
+ { allowBoolean: true, allowNumber: true },
145
+ ],
146
+ '@typescript-eslint/strict-boolean-expressions': 'off',
147
+ '@typescript-eslint/switch-exhaustiveness-check': 'error',
148
+ '@typescript-eslint/typedef': 'off',
149
+ },
150
+ })