productive-eslint 2.0.4 → 3.1.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.
package/FIXES.md ADDED
@@ -0,0 +1,1039 @@
1
+ # productive-eslint: Fix Guide
2
+
3
+ > Rules with autofix are omitted — run `eslint --fix` first.
4
+
5
+ ## JavaScript
6
+
7
+ ### default-case
8
+ Add a `default` case to every `switch` statement. Treat the `default` case as an unreachable scenario and throw an error (e.g., `default: throw new Error('Unknown case: ...')`).
9
+
10
+ ### grouped-accessor-pairs
11
+ Place getter and setter for the same property next to each other. Getter should come first.
12
+
13
+ ### id-length
14
+ Rename the identifier to be at least 2 characters long. The only allowed single-character name is `t` (for i18n). Common renames: `e` → `err`/`event`, `i` → `index`, `x`/`y` → descriptive names like `row`/`col`, `_` → `_unused`.
15
+
16
+ ### no-empty-static-block
17
+ Remove empty `static {}` blocks from classes or add meaningful content.
18
+
19
+ ### no-inner-declarations
20
+ Move function/variable declarations out of nested blocks to the module or function scope.
21
+
22
+ ### no-object-constructor
23
+ Replace `new Object()` with an object literal `{}`.
24
+
25
+ ### no-shadow
26
+ Rename the inner variable so it does not shadow the variable from an outer scope. Use a more specific name that reflects the inner variable's purpose — for example, if both scopes have `result`, rename the inner one to `mappedResult` or a domain-specific name.
27
+
28
+ ### no-unused-private-class-members
29
+ Remove unused private class members (`#field`, `#method()`) or reference them.
30
+
31
+ ### no-useless-concat
32
+ Merge adjacent string literals into a single string instead of concatenating.
33
+ ```js
34
+ // Bad
35
+ const a = 'a' + 'b'
36
+ // Good
37
+ const a = 'ab'
38
+ ```
39
+
40
+ ### consistent-this
41
+ Prefer refactoring to use an arrow function instead, which avoids the need to capture `this` at all. If capturing `this` is truly necessary, name the variable `that` — no other name is allowed.
42
+
43
+ ### for-direction
44
+ Fix the loop counter update so the loop can terminate. Ensure `i++` for `i < n` and `i--` for `i > n`.
45
+
46
+ ### new-cap
47
+ Capitalize constructor function names (start with uppercase). The config sets `capIsNew: false`, so the rule primarily fires when a lowercase function is used with `new`. Rename the constructor to start with an uppercase letter, or if the function is not a constructor, remove the `new` keyword.
48
+
49
+ ### no-bitwise
50
+ Replace bitwise operators with their intended equivalents. Common fixes: `a | b` → `a || b`, `a & b` → `a && b`, `~~x` or `x | 0` → `Math.trunc(x)`, `x << 1` → `x * 2`, `x >> 1` → `Math.floor(x / 2)`. If bitwise operations are genuinely needed (flags, binary protocols), add an `eslint-disable-next-line` comment with justification.
51
+
52
+ ### no-constant-binary-expression
53
+ Rewrite the binary expression that always evaluates to the same result. Common causes: `a ?? 'default'` where `a` is never nullish, `obj && {}` which always evaluates to `{}`, or `x || true` which is always `true`. Identify which operand makes the expression constant and either remove the redundant check or fix the logic.
54
+
55
+ ### no-constant-condition
56
+ Replace the constant value in `if`/`while`/ternary with a real boolean expression.
57
+
58
+ ### no-constructor-return
59
+ Remove the `return` statement from the constructor. Constructors must not return values.
60
+
61
+ ### no-invalid-this
62
+ Move the `this` reference inside a class method, object method, or constructor. If `this` appears in a standalone function, convert it to a class method or pass the needed context as a parameter. If the function is a callback, convert it to an arrow function (which inherits `this` from the enclosing scope).
63
+
64
+ ### no-param-reassign
65
+ Do not reassign function parameters. Create a new variable instead. Property mutations are allowed for: `accumulator`, `ctx`, `context`, `req`, `request`, `res`, `response`, `$scope`, `staticContext`, `ref`, `model`, and names ending with `Ref`/`Model`.
66
+
67
+ ### no-promise-executor-return
68
+ Do not return a value from a Promise executor. If the executor uses an arrow function with an implicit return (e.g., `=> resolve(1)`), wrap the body in braces. If the executor explicitly uses `return someValue`, remove the `return` keyword or replace with `resolve(someValue)`.
69
+ ```js
70
+ // Bad
71
+ new Promise((resolve) => resolve(1))
72
+ // Good
73
+ new Promise((resolve) => { resolve(1) })
74
+ ```
75
+
76
+ ### no-return-assign
77
+ Do not use assignment inside a `return` statement. Assign to a variable first, then return it.
78
+
79
+ ### no-script-url
80
+ Do not use `javascript:` URLs. Use event handlers instead.
81
+
82
+ ### no-sequences
83
+ Do not use the comma operator to chain expressions. Split each comma-separated expression into its own statement. In `return` statements like `return (x++, x)`, extract the side effect to a line before the return: `x++; return x;`.
84
+
85
+ ### complexity
86
+ Reduce cyclomatic complexity to 12 or below. Each `if`, `else if`, `case`, `for`, `while`, `do`, `&&`, `||`, `??`, and ternary `?` adds 1 to complexity. To reduce: extract groups of related conditions into helper functions, replace `if/else if` chains with lookup objects/maps, use early returns to eliminate `else` branches.
87
+
88
+ ### max-depth
89
+ Reduce block nesting depth to 2 or below. Each nested `if`, `for`, `while`, `switch`, or `try` adds one level. To reduce: invert conditions and use early `return`/`continue` (guard clauses), extract deeply nested logic into separate functions, merge consecutive `if` conditions with `&&`.
90
+ ```js
91
+ // Bad (depth 3)
92
+ if (a) {
93
+ if (b) {
94
+ if (c) { /* ... */ }
95
+ }
96
+ }
97
+ // Good
98
+ if (!a || !b) return
99
+ if (c) { /* ... */ }
100
+ ```
101
+
102
+ ### require-atomic-updates
103
+ Do not read a variable before `await`/`yield` and then assign to it after — another async operation may have changed its value. Fix by re-reading the variable after the `await`, using a local temporary variable, or restructuring so the read and write happen without an intervening `await`.
104
+
105
+ ## TypeScript (@typescript-eslint)
106
+
107
+ ### @typescript-eslint/class-literal-property-style
108
+ Always declare literal properties as `readonly` fields, not getters. If a getter simply returns a literal value, replace it with a `readonly` field assignment.
109
+
110
+ ### @typescript-eslint/default-param-last
111
+ Move parameters with default values to the end of the parameter list.
112
+
113
+ ### @typescript-eslint/explicit-function-return-type
114
+ Add an explicit return type to functions. Expressions passed as arguments are exempted (`allowExpressions: true`).
115
+ ```ts
116
+ // Bad
117
+ const fn = () => 1
118
+ // Good
119
+ const fn = (): number => 1
120
+ ```
121
+
122
+ ### @typescript-eslint/naming-convention
123
+ Rename the identifier to match the required convention. Read the ESLint error message to identify which selector was violated:
124
+ - `class`, `enum` — `StrictPascalCase` (e.g., `MyClass`, `MyEnum`)
125
+ - `enumMember` — `UPPER_CASE` (e.g., `MY_VALUE`)
126
+ - `interface` — `StrictPascalCase` with mandatory `I` prefix (e.g., `IMyInterface`)
127
+ - `typeAlias` — `StrictPascalCase` with mandatory `T` prefix (e.g., `TMyType`)
128
+ - `typeParameter` — `StrictPascalCase` (e.g., `TKey`, `TValue`)
129
+ - `variable` (const) — `strictCamelCase` for most values, `UPPER_CASE` for module-level constants
130
+ - `parameter` (unused) — prefix with `_`, use `camelCase` (e.g., `_unusedParam`)
131
+ - `objectLiteralProperty`, `import` — exempt, no rename needed
132
+
133
+ After renaming, update all references to the renamed identifier across the codebase.
134
+
135
+ ### @typescript-eslint/no-base-to-string
136
+ Do not coerce objects to string if they don't have a meaningful `toString()`. Add a `toString()` method or serialize explicitly.
137
+
138
+ ### @typescript-eslint/no-dynamic-delete
139
+ Replace `delete obj[key]` with `Map`/`Set` or use object rest destructuring to remove properties.
140
+
141
+ ### @typescript-eslint/no-empty-object-type
142
+ Do not use `{}` as a type. Use `Record<string, unknown>`, `object`, or `unknown` instead. Empty interfaces are allowed (`allowInterfaces: 'always'`).
143
+
144
+ ### @typescript-eslint/no-floating-promises
145
+ Handle every Promise: (1) add `await` before it — preferred fix inside `async` functions; (2) add `return` to propagate it to the caller; (3) append `.catch((error) => { /* handle */ })` for explicit error handling; (4) prefix with `void` only if the promise is intentionally fire-and-forget (e.g., logging, analytics). Do not use `void` as a blanket silencer.
146
+
147
+ ### @typescript-eslint/no-loop-func
148
+ Do not define functions inside loops that reference outer mutable variables. Extract the function outside the loop.
149
+
150
+ ### @typescript-eslint/no-magic-numbers
151
+ Extract the numeric literal into a named `const` with a descriptive name (e.g., `const MAX_RETRY_COUNT = 3`). Place it at module scope or the top of the enclosing block. Exempt (no extraction needed): `0`, `1`, `100`, `-1`, class field initializers, default parameter values, and enum values. The extracted variable must use `const` (`enforceConst: true`).
152
+
153
+ ### @typescript-eslint/no-redundant-type-constituents
154
+ Remove type constituents that are already covered by another constituent in the union/intersection.
155
+
156
+ ### @typescript-eslint/no-unnecessary-condition
157
+ The condition is always truthy or always falsy based on the TypeScript type. If the type is too narrow (e.g., `string` but the value can be `null` at runtime), widen the type to include the nullish case. If the condition is genuinely unnecessary (the type proves it), remove the `if` block and keep only the reachable branch's body.
158
+
159
+ ### @typescript-eslint/no-unnecessary-type-conversion
160
+ Remove unnecessary type conversions (e.g., `String(alreadyAString)`). The value is already the correct type.
161
+
162
+ ### @typescript-eslint/no-unsafe-argument
163
+ The argument is typed as `any`. Trace the value to its source and add a proper type annotation there. If the value comes from an untyped library, add a type assertion (e.g., `value as TExpectedType`) at the call site. If from `JSON.parse()`, validate the shape or assert the type.
164
+
165
+ ### @typescript-eslint/no-unsafe-assignment
166
+ The right-hand side is typed as `any`. Trace the `any` to its origin — often an untyped function return, `JSON.parse()`, or a library without type definitions. Add a type annotation or assertion at the source. Adding a type annotation only on the receiving variable (e.g., `const x: string = anyValue`) will NOT fix this — the source must be typed.
167
+
168
+ ### @typescript-eslint/no-unsafe-call
169
+ The value being called is typed as `any`. Add a type annotation to the variable or parameter that holds the function, specifying its call signature (e.g., `const handler: (event: Event) => void`). If the function comes from a third-party library, install its `@types/*` package.
170
+
171
+ ### @typescript-eslint/no-unsafe-enum-comparison
172
+ Compare enum values only to other members of the same enum, not to raw literals.
173
+
174
+ ### @typescript-eslint/no-unsafe-member-access
175
+ A property is being accessed on a value typed as `any`. Add a type annotation or interface to the parent object. If from `JSON.parse()` or an API response, define an interface for the shape and assert at the parse/fetch point. Type the parent object, not the accessed property.
176
+
177
+ ### @typescript-eslint/no-unsafe-return
178
+ The function returns a value typed as `any`. Add an explicit return type to the function, then trace the `any` inside the body and type it at its source. Simply adding a return type without fixing the internal `any` will produce a type error instead of silencing this rule.
179
+
180
+ ### @typescript-eslint/no-unsafe-unary-minus
181
+ Do not apply unary minus to `any`-typed values. Type the value as `number` first.
182
+
183
+ ### @typescript-eslint/no-useless-constructor
184
+ Remove constructors that only call `super()` with the same arguments. They are unnecessary.
185
+
186
+ ### @typescript-eslint/only-throw-error
187
+ Only throw `Error` objects (or subclasses). Do not throw strings or other non-Error values.
188
+
189
+ ### @typescript-eslint/related-getter-setter-pairs
190
+ If a property has a getter, add a setter and vice versa. They should have compatible types.
191
+
192
+ ### @typescript-eslint/require-array-sort-compare
193
+ Pass a compare function to `.sort()`. Without it, elements are sorted as strings.
194
+ ```ts
195
+ // Bad
196
+ numbers.sort()
197
+ // Good
198
+ numbers.sort((a, b) => a - b)
199
+ ```
200
+
201
+ ### @typescript-eslint/require-await
202
+ This function is `async` but has no `await`. If it performs no async work, remove `async`. If the function must return a `Promise` to satisfy an interface, return `Promise.resolve(value)` explicitly. If the function should be awaiting a call but `await` is missing, add the missing `await`.
203
+
204
+ ### @typescript-eslint/return-await
205
+ Use `return await` in `try`/`catch` blocks so exceptions are caught. Outside try/catch, return the promise directly.
206
+
207
+ ### @typescript-eslint/switch-exhaustiveness-check
208
+ Add a `case` for every member of the union/enum, or add a `default` case.
209
+
210
+ ### @typescript-eslint/unbound-method
211
+ Bind the method before passing it as a callback, or use an arrow function wrapper.
212
+ ```ts
213
+ // Bad
214
+ const fn = obj.method
215
+ // Good
216
+ const fn = obj.method.bind(obj)
217
+ // or
218
+ const fn = (...args) => obj.method(...args)
219
+ ```
220
+
221
+ ### @typescript-eslint/unified-signatures
222
+ Merge overload signatures that differ only in one parameter into a single signature using a union type.
223
+
224
+ ### @typescript-eslint/class-methods-use-this
225
+ This method does not reference `this`. Preferred fix: make it `static` and update all call sites from `instance.method()` to `ClassName.method()`. If the method is part of an interface contract, keep it as an instance method. Do not add a meaningless `this` reference just to satisfy the rule.
226
+
227
+ ### @typescript-eslint/init-declarations
228
+ Initialize variables at declaration. Do not use `let x;` without an initial value.
229
+
230
+ ### @typescript-eslint/max-params
231
+ Reduce function parameters to 3 or fewer. Group related parameters into a single options object. Define an interface for it with the `I` prefix per naming convention (e.g., `ICreateUserOptions`). Keep the 1–2 most essential parameters positional and move the rest into the options object.
232
+
233
+ ### @typescript-eslint/no-extraneous-class
234
+ This class contains only static members. Convert each static method to a standalone exported function and each static property to an exported `const`. Remove the class and update all call sites from `ClassName.method()` to direct function imports.
235
+
236
+ ### @typescript-eslint/no-invalid-void-type
237
+ Do not use `void` as a type except as a return type. Use `undefined` instead.
238
+
239
+ ### @typescript-eslint/no-misused-promises
240
+ An async function is passed where a void-returning callback is expected (e.g., event handlers, `forEach`). Wrap it in a non-async wrapper: `(event) => { void handleClick(event) }`. For error handling: `(event) => { handleClick(event).catch(handleError) }`. Do not make the callback itself `async` if the caller doesn't expect a Promise return.
241
+
242
+ ### @typescript-eslint/no-misused-spread
243
+ Do not spread a value into an incompatible context (e.g., spreading a string into an array of numbers).
244
+
245
+ ### @typescript-eslint/no-mixed-enums
246
+ Do not mix string and number members in the same enum. Use one type consistently.
247
+
248
+ ### @typescript-eslint/parameter-properties
249
+ Do not use TypeScript parameter properties (e.g., `constructor(private name: string)`). Instead, declare the field explicitly in the class body (`private name: string`) and assign it in the constructor (`this.name = name`).
250
+
251
+ ### @typescript-eslint/prefer-enum-initializers
252
+ Explicitly initialize all enum members to avoid fragile implicit numbering.
253
+
254
+ ### @typescript-eslint/prefer-promise-reject-errors
255
+ Reject promises only with `Error` objects. Do not reject with strings or `undefined`.
256
+
257
+ ### @typescript-eslint/restrict-template-expressions
258
+ A value embedded in a template literal is not a `string`, `number`, `boolean`, or `bigint`. For objects, access a specific string property (e.g., `${error.message}` instead of `${error}`). For `undefined`/`null`, use nullish coalescing: `${value ?? 'default'}`. For arrays, use `${arr.join(', ')}`. As a last resort, call `String(value)`.
259
+
260
+ ### @typescript-eslint/no-non-null-assertion
261
+ Remove the `!` operator. Preferred alternatives: (1) use optional chaining `obj?.prop` instead of `obj!.prop`; (2) use nullish coalescing `value ?? defaultValue` instead of `value!`; (3) add an explicit type guard (e.g., `if (value === null) throw new Error(...)`) — preferred over `!` because it fails loudly at runtime; (4) for `.find()` returning `T | undefined`, add an `if` check for the `undefined` case. Do not replace `!` with `as T` — that is equally unsafe.
262
+
263
+ ### @typescript-eslint/no-explicit-any
264
+ Replace `any` with a proper type: (1) if the shape is known, use that type or define an interface; (2) if the value could be anything, use `unknown` and add type guards before using it; (3) if the function should work with multiple types, use a generic (`<T>`); (4) for catch clause variables, use `unknown` and narrow with `instanceof Error`; (5) for event handlers, use the specific event type (e.g., `React.ChangeEvent<HTMLInputElement>`).
265
+
266
+ ## Unicorn
267
+
268
+ ### unicorn/no-empty-file
269
+ If the file is a placeholder (e.g., an `index.ts` barrel file), add the necessary exports. If the file is truly unused, delete it and remove all imports referencing it.
270
+
271
+ ### unicorn/no-unused-properties
272
+ Determine whether the unused property is needed downstream. If it is, add the missing reference. If not, remove the property definition. Check for typos in property names — a misspelled property is the most common cause.
273
+
274
+ ### unicorn/no-useless-switch-case
275
+ Remove switch cases that have no unique logic and just fall through to the default.
276
+
277
+ ### unicorn/prefer-blob-reading-methods
278
+ Use `blob.text()` or `blob.arrayBuffer()` instead of `FileReader`.
279
+
280
+ ### unicorn/prefer-code-point
281
+ Use `String.prototype.codePointAt()` and `String.fromCodePoint()` instead of `charCodeAt()`/`fromCharCode()`.
282
+
283
+ ### unicorn/prefer-default-parameters
284
+ Use default parameter syntax instead of manually checking for `undefined`.
285
+ ```js
286
+ // Bad
287
+ function fn(x) { x = x || 'default' }
288
+ // Good
289
+ function fn(x = 'default') {}
290
+ ```
291
+
292
+ ### unicorn/prefer-dom-node-text-content
293
+ Use `node.textContent` instead of `node.innerText`.
294
+
295
+ ### unicorn/prefer-event-target
296
+ Replace `EventEmitter` with the native `EventTarget` API: use `new EventTarget()`, `dispatchEvent(new CustomEvent('name', { detail }))`, and `addEventListener('name', handler)` instead of `emit()`/`on()`. This only applies to browser code — if the code runs in Node.js only, suppress with an inline disable comment.
297
+
298
+ ### unicorn/prefer-logical-operator-over-ternary
299
+ Use `||` or `??` instead of a ternary that checks the same condition.
300
+ ```js
301
+ // Bad
302
+ const x = a ? a : b
303
+ // Good
304
+ const x = a || b
305
+ ```
306
+
307
+ ### unicorn/prefer-structured-clone
308
+ Use `structuredClone(obj)` instead of `JSON.parse(JSON.stringify(obj))`.
309
+
310
+ ### unicorn/prefer-top-level-await
311
+ Replace async IIFEs (`(async () => { ... })()`) with top-level `await`. Move the awaited statements directly to module scope. This requires the file to be an ES module — if it uses `require()`/`module.exports`, first convert to ESM.
312
+
313
+ ### unicorn/require-post-message-target-origin
314
+ Always pass a `targetOrigin` as the second argument to `postMessage()`. Use the specific origin of the target window (e.g., `'https://example.com'`). Use `'*'` only if the message contains no sensitive data.
315
+
316
+ ### unicorn/consistent-destructuring
317
+ If you destructured some properties from an object, use the destructured variables everywhere — do not access those same properties via dot notation on the original object. Either add the missing property to the destructuring pattern, or remove it from destructuring and use dot notation throughout.
318
+
319
+ ### unicorn/no-abusive-eslint-disable
320
+ Do not use bare `eslint-disable` without specifying rule names. Always specify which rules to disable.
321
+
322
+ ### unicorn/no-accessor-recursion
323
+ Do not reference `this.propName` inside the getter or setter for `propName` — this causes infinite recursion. Use a private backing field (e.g., `this.#propName`) to store the underlying value, and read/write the backing field inside the accessor.
324
+
325
+ ### unicorn/no-array-callback-reference
326
+ Do not pass function references directly to array methods. Use an inline arrow function to avoid unexpected arguments.
327
+ ```js
328
+ // Bad
329
+ items.map(Number.parseInt)
330
+ // Good
331
+ items.map((item) => Number.parseInt(item, 10))
332
+ ```
333
+
334
+ ### unicorn/no-magic-array-flat-depth
335
+ Extract the `.flat()` depth argument into a named constant when it is greater than 1.
336
+
337
+ ### unicorn/no-negation-in-equality-check
338
+ Move the negation outside the equality check.
339
+ ```js
340
+ // Bad
341
+ if (!a === b) {}
342
+ // Good
343
+ if (a !== b) {}
344
+ ```
345
+
346
+ ### unicorn/no-unreadable-array-destructuring
347
+ Avoid destructuring with many skipped elements. Access by index instead.
348
+ ```js
349
+ // Bad
350
+ const [,,, d] = arr
351
+ // Good
352
+ const d = arr[3]
353
+ ```
354
+
355
+ ### unicorn/no-array-method-this-argument
356
+ Do not pass a `thisArg` to array methods. Use an arrow function or `.bind()` instead.
357
+
358
+ ### unicorn/no-await-in-promise-methods
359
+ Do not `await` individual promises inside `Promise.all()`, `Promise.race()`, etc. — the `await` forces sequential execution, defeating the purpose. Remove the `await` from each element.
360
+ ```js
361
+ // Bad
362
+ await Promise.all([await fetchA(), await fetchB()])
363
+ // Good
364
+ await Promise.all([fetchA(), fetchB()])
365
+ ```
366
+
367
+ ### unicorn/no-document-cookie
368
+ Do not use `document.cookie` directly. Use the Cookie Store API or a cookie utility library.
369
+
370
+ ### unicorn/no-invalid-remove-event-listener
371
+ The function reference passed to `removeEventListener()` must be the exact same reference passed to `addEventListener()`. Store the handler in a variable at the point where `addEventListener()` is called, then pass that same variable to `removeEventListener()`.
372
+ ```js
373
+ // Bad
374
+ el.addEventListener('click', () => handle())
375
+ el.removeEventListener('click', () => handle()) // Different reference!
376
+ // Good
377
+ const handler = () => handle()
378
+ el.addEventListener('click', handler)
379
+ el.removeEventListener('click', handler)
380
+ ```
381
+
382
+ ### unicorn/no-object-as-default-parameter
383
+ Do not use object literals as default parameter values — passing `{ a: 2 }` would lose the default for other properties. Use destructured parameters with individual defaults instead.
384
+ ```js
385
+ // Bad
386
+ function fn(opts = { a: 1, b: 2 }) {}
387
+ // Good
388
+ function fn({ a = 1, b = 2 } = {}) {}
389
+ ```
390
+
391
+ ## SonarJS
392
+
393
+ ### sonarjs/no-fallthrough
394
+ Add a `break`, `return`, or `throw` at the end of each `case` block. If multiple cases share the same logic, stack the `case` labels on consecutive lines with no code between them instead of using fall-through.
395
+
396
+ ### sonarjs/prefer-immediate-return
397
+ When a variable is declared, assigned, and then immediately returned on the next line, remove the variable and return the value directly. Replace `const result = expr; return result;` with `return expr;`. Keep the variable only if its name provides important documentation of the expression's purpose.
398
+
399
+ ### sonarjs/no-redundant-boolean
400
+ Remove redundant boolean literals. Replace `x === true` with `x`, `x === false` with `!x`, `x ? true : false` with `x`, `x ? false : true` with `!x`, `return condition ? true : false` with `return condition`.
401
+
402
+ ### sonarjs/no-redundant-jump
403
+ Remove unnecessary `return`, `continue`, or `break` at the end of a block.
404
+
405
+ ### sonarjs/non-existent-operator
406
+ Fix the typo: `=!` should be `!=`, `=+` should be `+=`, `=-` should be `-=`.
407
+
408
+ ### sonarjs/public-static-readonly
409
+ Mark public static fields as `readonly` if they are never reassigned.
410
+
411
+ ### sonarjs/bool-param-default
412
+ Provide a default value for boolean parameters.
413
+
414
+ ### sonarjs/comma-or-logical-or-case
415
+ Each `case` in a `switch` should have its own `case` label. Do not use comma-separated values.
416
+
417
+ ### sonarjs/future-reserved-words
418
+ Do not use future reserved words (`implements`, `interface`, `package`, etc.) as identifiers.
419
+
420
+ ### sonarjs/index-of-compare-to-positive-number
421
+ Compare `indexOf()` result to `-1`, not to `> 0` (which misses index 0).
422
+
423
+ ### sonarjs/link-with-target-blank
424
+ Add `rel="noopener noreferrer"` to links with `target="_blank"`.
425
+
426
+ ### sonarjs/no-array-delete
427
+ Do not use `delete` on array elements. Use `.splice()` instead.
428
+
429
+ ### sonarjs/no-duplicate-in-composite
430
+ Remove duplicate types in union or intersection types.
431
+
432
+ ### sonarjs/no-for-in-iterable
433
+ Do not use `for...in` on arrays or iterables. Use `for...of` instead.
434
+
435
+ ### sonarjs/no-function-declaration-in-block
436
+ Move function declarations out of `if`/`else`/`for`/`while` blocks.
437
+
438
+ ### sonarjs/no-global-this
439
+ Avoid using `globalThis`. Import or declare dependencies explicitly.
440
+
441
+ ### sonarjs/no-globals-shadowing
442
+ Do not shadow global variables (`undefined`, `NaN`, `Infinity`, etc.) with local declarations.
443
+
444
+ ### sonarjs/no-identical-conditions
445
+ Remove or change duplicate conditions in `if`/`else if` chains.
446
+
447
+ ### sonarjs/no-identical-expressions
448
+ Do not use the same expression on both sides of a binary operator (e.g., `a === a`, `x - x`). Determine which side is a mistake by looking at surrounding context and variable names, then fix the incorrect side. If both sides are genuinely the same and this is a no-op, remove the entire expression.
449
+
450
+ ### sonarjs/no-identical-functions
451
+ Extract the shared logic into a single function and have the duplicates call it. Place the shared function in the nearest common scope. Name it after what it does, not where it came from.
452
+
453
+ ### sonarjs/no-ignored-return
454
+ Use the return value of pure methods (`.map()`, `.filter()`, `.slice()`, `.trim()`, `.replace()`, etc.) — assign the result to a variable or return it. If you intended a side-effect loop, use `.forEach()` or a `for` loop instead. If you intended to mutate, use the mutating alternative (e.g., `.splice()` instead of `.slice()`).
455
+
456
+ ### sonarjs/no-in-misuse
457
+ Use `Array.prototype.includes()` or `indexOf()` instead of `in` for arrays. `in` checks keys, not values.
458
+
459
+ ### sonarjs/no-incorrect-string-concat
460
+ When `+` is used with a mix of strings and numbers, ensure the operation is intentional. If you intend string concatenation, convert the numeric operand with `String(num)` or use a template literal. If you intend numeric addition, ensure both operands are numbers via `Number(str)` or `parseInt()`.
461
+
462
+ ### sonarjs/no-internal-api-use
463
+ Do not import from internal/private paths of libraries.
464
+
465
+ ### sonarjs/no-misleading-array-reverse
466
+ `.reverse()` and `.sort()` mutate the array in-place and return the same reference. If mutation is acceptable, call the method without assigning (`arr.sort()`). If you need a new array without mutating the original, spread-copy first: `[...arr].sort()` or `[...arr].reverse()`.
467
+
468
+ ### sonarjs/no-nested-template-literals
469
+ Extract nested template literals into variables.
470
+
471
+ ### sonarjs/no-redundant-assignments
472
+ Remove assignments where the value is immediately overwritten.
473
+
474
+ ### sonarjs/no-redundant-optional
475
+ Replace `?.` with `.` when the value is guaranteed to be non-nullish (the value comes from a non-optional property, was already null-checked, or the TypeScript type excludes `null`/`undefined`).
476
+
477
+ ### sonarjs/no-selector-parameter
478
+ Do not pass CSS selectors as parameters. Pass the element directly instead.
479
+
480
+ ### sonarjs/no-small-switch
481
+ Replace `switch` statements with fewer than 3 cases with `if`/`else`.
482
+
483
+ ### sonarjs/no-try-promise
484
+ Synchronous `try/catch` cannot catch asynchronous rejections. Fix by making the enclosing function `async` and `await`ing the promise inside the `try` block, or remove `try/catch` and chain `.catch()` on the promise instead.
485
+
486
+ ### sonarjs/no-undefined-assignment
487
+ Do not assign `undefined` explicitly. Use `let x;` or `delete obj.prop` instead.
488
+
489
+ ### sonarjs/no-unthrown-error
490
+ Created `Error` objects must be thrown. Add `throw` before `new Error(...)`.
491
+
492
+ ### sonarjs/no-unused-collection
493
+ A collection (array, Set, Map) is populated but never read. If it is needed, add the missing code that reads from it (return it, pass to another function, iterate). If it is dead code, remove the declaration and all its `.push()`/`.add()`/`.set()` calls. Check if it was meant to be returned from the function.
494
+
495
+ ### sonarjs/no-unused-function-argument
496
+ Prefix unused parameters with `_` (e.g., `_event`). Do not remove the parameter if a later positional parameter IS used — you must keep all preceding parameters. Only remove outright if it is the last parameter and no callers pass a value for it. For callbacks with a fixed signature (event handlers, middleware), always prefix with `_` rather than removing.
497
+
498
+ ### sonarjs/no-use-of-empty-return-value
499
+ Do not use the return value of functions that return `void`.
500
+
501
+ ### sonarjs/no-useless-intersection
502
+ The intersection results in `never` due to incompatible constituents (e.g., `string & number`). If one type is correct, keep it and remove the `&` and the other type. If the intersection was meant to be a union, change `&` to `|`. If on object types with conflicting properties, fix the conflicting property to be compatible.
503
+
504
+ ### sonarjs/object-alt-content
505
+ Add alternative text to `<object>` elements for accessibility.
506
+
507
+ ### sonarjs/post-message
508
+ Specify an explicit target origin in `postMessage()` instead of `*`.
509
+
510
+ ### sonarjs/prefer-promise-shorthand
511
+ Use `Promise.resolve()` / `Promise.reject()` instead of `new Promise((resolve) => resolve(...))`.
512
+
513
+ ### sonarjs/reduce-initial-value
514
+ Always provide an initial value to `.reduce()`.
515
+
516
+ ### sonarjs/strings-comparison
517
+ Use `localeCompare()` for locale-aware string comparison instead of `<` / `>`.
518
+
519
+ ### sonarjs/table-header
520
+ Add `<th>` elements to `<table>` for accessibility.
521
+
522
+ ### sonarjs/table-header-reference
523
+ Use the `headers` attribute on `<td>` to reference `<th>` `id`s in complex tables.
524
+
525
+ ### sonarjs/expression-complexity
526
+ Reduce expression complexity to at most 2 logical/ternary operators per expression. Each `&&`, `||`, `??`, and `? :` counts as 1. Extract sub-expressions into descriptive `const` variables (e.g., `const isEligible = age >= 18 && hasConsent`), then combine the named variables in the final expression.
527
+
528
+ ### sonarjs/no-all-duplicated-branches
529
+ Every branch of this `if`/`else` (or ternary/switch) has the same body, making the condition pointless. Remove the conditional entirely and keep the body as unconditional code. If the branches should differ, fix the return values — this is likely a copy-paste bug.
530
+
531
+ ### sonarjs/no-async-constructor
532
+ Constructors cannot be `async`. Move async logic into a static `async` factory method (e.g., `static async create(): Promise<ClassName>`) that creates the instance, performs async work, and returns it. Update all `new ClassName()` call sites to `await ClassName.create()`.
533
+
534
+ ### sonarjs/no-invariant-returns
535
+ Every code path returns the same value, making branching pointless. If the function genuinely always returns the same value, remove the branching and return directly. If branches should return different values, fix the incorrect return statements — this is likely a copy-paste bug.
536
+
537
+ ### sonarjs/no-nested-switch
538
+ Do not nest `switch` statements. Extract the inner switch into a separate function.
539
+
540
+ ### sonarjs/too-many-break-or-continue-in-loop
541
+ This loop has too many `break`/`continue` statements. Refactor by: extracting the loop body into a function and using early `return` instead of `continue`; replacing the loop with array methods (`.filter()`, `.find()`, `.some()`, `.every()`) where applicable; or consolidating conditions into a single guard clause at the top of the loop.
542
+
543
+ ## Promise
544
+
545
+ ### promise/always-return
546
+ Always return a value inside every `.then()` callback. If no meaningful value is needed, add `return undefined` as the last statement. Preferred: refactor the `.then()` chain to `async`/`await`.
547
+
548
+ ### promise/catch-or-return
549
+ Every promise chain must either be returned to the calling function (so the caller handles rejection) or terminate with `.catch()`. If the promise is a standalone statement, append `.catch((error) => { /* handle */ })`. With `async`/`await`, wrap in `try`/`catch` instead.
550
+
551
+ ### promise/no-multiple-resolved
552
+ Do not call `resolve()`/`reject()` more than once. Add early `return` after each `resolve()`/`reject()` call to prevent subsequent calls. If conditional branches each call `resolve()`/`reject()`, ensure they are mutually exclusive (use `if`/`else`, not sequential `if` blocks).
553
+
554
+ ### promise/no-return-in-finally
555
+ Do not return values in `.finally()`. It silently swallows errors.
556
+
557
+ ### promise/no-return-wrap
558
+ Inside `.then()`, replace `return Promise.resolve(value)` with `return value`. Inside `.catch()`, replace `return Promise.reject(error)` with `throw error`. The `.then()`/`.catch()` callbacks already wrap return values in promises automatically.
559
+
560
+ ### promise/param-names
561
+ Name Promise executor parameters `resolve` and `reject`.
562
+
563
+ ### promise/valid-params
564
+ Pass the correct number of arguments to Promise methods (`.then()`, `.catch()`, `.finally()`).
565
+
566
+ ### promise/prefer-await-to-then
567
+ Refactor `.then()` chains to `async`/`await`. Make the enclosing function `async`, replace each `.then(callback)` with an `await` expression assigned to a variable, and replace `.catch(callback)` with a `try`/`catch` block.
568
+
569
+ ### promise/no-nesting
570
+ Do not nest `.then()` inside another `.then()`. Flatten the chain by returning the inner promise from the outer `.then()` and adding a new `.then()` at the top level. Preferred: refactor the entire chain to `async`/`await`, which eliminates nesting naturally.
571
+
572
+ ### promise/no-promise-in-callback
573
+ Do not create promises inside callback-style functions (e.g., Node.js `(err, result) => {}` callbacks). Wrap the callback-based API in a promise using `new Promise()` or `util.promisify()`, then use `async`/`await` to compose with other async operations.
574
+
575
+ ## Import
576
+
577
+ ### import/extensions
578
+ Remove `.js`, `.jsx`, `.ts`, `.tsx` extensions from import paths (e.g., `import Foo from './Foo.ts'` → `import Foo from './Foo'`). Keep extensions for non-code files (`.json`, `.css`, `.svg`) — this rule only applies to JS/TS source files.
579
+
580
+ ### import/no-commonjs
581
+ Replace `require('...')` with `import ... from '...'`, `module.exports = ...` with `export default ...`, and `exports.foo = ...` with `export const foo = ...`. For dynamic/conditional require, use `await import('...')` instead.
582
+
583
+ ### import/no-mutable-exports
584
+ Change exported `let`/`var` to `const`. If the value genuinely mutates, do not export it directly — export a getter function instead (e.g., `export function getFoo() { return foo; }`).
585
+
586
+ ### import/no-named-default
587
+ Use the default import syntax instead of `import { default as Name }`.
588
+
589
+ ### import/no-self-import
590
+ A module must not import itself. Remove the self-referencing `import` and call the local binding directly instead.
591
+
592
+ ### import/export
593
+ Do not have multiple `export default` or duplicate named exports. If there are two default exports, keep one and convert the other to a named export. If the same name is exported twice, rename one of them. Check re-exports (`export ... from`) that may conflict with local exports.
594
+
595
+ ### import/no-cycle
596
+ Remove circular `import` dependencies. To fix: (1) extract the shared types/logic into a new module that both files can import without a loop; (2) move one import to a dynamic `import()` at the point of use if the dependency is only needed at runtime; (3) if the cycle is caused by type imports only, switch to `import type` which is erased at runtime and does not cause circular dependency issues.
597
+
598
+ ## Vue
599
+
600
+ ### vue/block-lang
601
+ `<script>` blocks must use `lang="ts"`.
602
+
603
+ ### vue/comment-directive
604
+ Ensure `eslint-disable` comments in `<template>` specify rule names.
605
+
606
+ ### vue/component-api-style
607
+ Use `<script setup>` instead of Options API or non-setup Composition API.
608
+
609
+ ### vue/custom-event-name-casing
610
+ Use `camelCase` for custom event names in `$emit()`.
611
+
612
+ ### vue/define-props-declaration
613
+ Use type-based props declaration (`defineProps<{ ... }>()`) instead of runtime declaration.
614
+
615
+ ### vue/define-props-destructuring
616
+ Destructure props from `defineProps()` for cleaner template references.
617
+
618
+ ### vue/enforce-style-attribute
619
+ `<style>` blocks must use `module` attribute. Scoped styles via `<style module>`.
620
+
621
+ ### vue/jsx-uses-vars
622
+ Variables used in JSX are marked as used. This rule prevents false `no-unused-vars` errors.
623
+
624
+ ### vue/no-arrow-functions-in-watch
625
+ Do not use arrow functions in `watch`. Use a regular function to access component `this`.
626
+
627
+ ### vue/no-deprecated-delete-set
628
+ Do not use `$delete` or `$set` — they are removed in Vue 3. To delete a property, use `delete obj.key`. To set a reactive property, assign directly (`obj.key = value`) — Vue 3 reactivity tracks this natively.
629
+
630
+ ### vue/no-deprecated-dollar-listeners-api
631
+ Do not use `$listeners`. It is removed in Vue 3. Use `v-bind="$attrs"` instead.
632
+
633
+ ### vue/no-deprecated-events-api
634
+ Do not use `$on`, `$off`, `$once`. Use an external event bus or composables.
635
+
636
+ ### vue/no-deprecated-filter
637
+ Do not use Vue filters (`{{ value | filter }}`). Use computed properties or methods.
638
+
639
+ ### vue/no-deprecated-functional-template
640
+ Do not use `<template functional>`. Use `<script setup>` for stateless components.
641
+
642
+ ### vue/no-deprecated-html-element-is
643
+ Do not use `is` attribute on HTML elements. Use `<component :is="...">` instead.
644
+
645
+ ### vue/no-deprecated-inline-template
646
+ Do not use the `inline-template` attribute. Use slots instead.
647
+
648
+ ### vue/no-deprecated-model-definition
649
+ Use `defineModel()` or `modelValue` prop instead of deprecated `model` option.
650
+
651
+ ### vue/no-deprecated-props-default-this
652
+ Do not use `this` in props `default` functions — `this` is `undefined` in Vue 3. Use a plain value or a factory function that derives the default without `this`. If you need another prop's value, use a computed property instead.
653
+
654
+ ### vue/no-deprecated-router-link-tag-prop
655
+ Do not use the `tag` prop on `<router-link>`. Use the `v-slot` API.
656
+
657
+ ### vue/no-deprecated-v-is
658
+ Do not use `v-is` directive. Use `:is` with `<component>` instead.
659
+
660
+ ### vue/no-deprecated-v-on-native-modifier
661
+ Do not use `.native` modifier on `v-on`. In Vue 3, all events are native by default.
662
+
663
+ ### vue/no-deprecated-vue-config-keycodes
664
+ Do not use `Vue.config.keyCodes`. Use key aliases directly (e.g., `@keyup.enter`).
665
+
666
+ ### vue/no-dupe-v-else-if
667
+ Remove duplicate conditions in `v-if`/`v-else-if` chains.
668
+
669
+ ### vue/no-duplicate-attributes
670
+ Do not use duplicate attributes on the same element.
671
+
672
+ ### vue/no-duplicate-attr-inheritance
673
+ When using `inheritAttrs: false`, do not duplicate attributes that come from `$attrs`.
674
+
675
+ ### vue/no-empty-pattern
676
+ Do not use empty destructuring patterns (e.g., `{}` or `[]`) in templates. Either destructure specific properties (e.g., `{ name }`) or remove the destructuring and use the whole object.
677
+
678
+ ### vue/no-export-in-script-setup
679
+ Do not use `export` in `<script setup>`. Use `defineExpose()` for public API.
680
+
681
+ ### vue/no-expose-after-await
682
+ Do not call `defineExpose()` after an `await`. Move it before any async operation.
683
+
684
+ ### vue/no-irregular-whitespace
685
+ Remove irregular whitespace characters from templates.
686
+
687
+ ### vue/no-lifecycle-after-await
688
+ Do not register lifecycle hooks after `await`. Move hook registration before any async operation.
689
+
690
+ ### vue/no-lone-template
691
+ Do not use `<template>` without directives (`v-if`, `v-for`, `v-slot`). It serves no purpose.
692
+
693
+ ### vue/no-loss-of-precision
694
+ Do not use number literals that lose precision. Use `BigInt` (e.g., `9007199254740993n`) for very large integers, or use a string representation if exact precision is needed.
695
+
696
+ ### vue/no-multiple-objects-in-class
697
+ Do not pass multiple object expressions to `:class`. Merge them into one object.
698
+
699
+ ### vue/no-multiple-slot-args
700
+ Slot functions must accept only a single argument (the slot props object).
701
+
702
+ ### vue/no-mutating-props
703
+ Do not mutate props directly. Emit an event to let the parent component update the value.
704
+
705
+ ### vue/no-parsing-error
706
+ Fix template parsing errors (unclosed tags, invalid attributes, etc.).
707
+
708
+ ### vue/no-ref-object-reactivity-loss
709
+ Do not destructure or spread ref objects — this loses reactivity. Use `.value` or `toRefs()`.
710
+
711
+ ### vue/no-reserved-component-names
712
+ Do not use HTML element names (e.g., `button`, `div`) or Vue built-in names (e.g., `Transition`, `KeepAlive`) as component names. Rename to something domain-specific (e.g., `AppButton`, `BaseCard`).
713
+
714
+ ### vue/no-reserved-keys
715
+ Do not use reserved Vue instance property names (`$data`, `$props`, etc.) as component data keys.
716
+
717
+ ### vue/no-reserved-props
718
+ Do not use reserved prop names (`key`, `ref`, `is`, `slot`).
719
+
720
+ ### vue/no-restricted-block
721
+ Do not use restricted SFC blocks as configured by the project. Check the ESLint config for which blocks are restricted and remove or replace them accordingly.
722
+
723
+ ### vue/no-restricted-syntax
724
+ Do not use `DebuggerStatement`, `LabeledStatement`, `WithStatement`. Do not use `reactive()` — use `ref()` instead for code consistency.
725
+
726
+ ### vue/no-restricted-v-bind
727
+ Do not bind `v-` prefixed attributes with `v-bind`.
728
+
729
+ ### vue/no-root-v-if
730
+ Do not use `v-if` on the root element of a template. It causes the component to be destroyed and recreated.
731
+
732
+ ### vue/no-side-effects-in-computed-properties
733
+ Do not mutate state or trigger side effects inside computed properties. Use `watch` or `watchEffect`.
734
+
735
+ ### vue/no-template-key
736
+ Do not put `key` on `<template>`. Place it on the child element.
737
+
738
+ ### vue/no-template-shadow
739
+ Do not shadow variables from outer scopes in `v-for` or `v-slot`.
740
+
741
+ ### vue/no-template-target-blank
742
+ Add `rel="noopener noreferrer"` to template links with `target="_blank"`.
743
+
744
+ ### vue/no-textarea-mustache
745
+ Do not use mustache interpolation in `<textarea>`. Use `v-model` instead.
746
+
747
+ ### vue/no-unused-components
748
+ Remove imported/registered components that are not used in the template.
749
+
750
+ ### vue/no-unused-refs
751
+ Remove template refs that are never used in `<script>`.
752
+
753
+ ### vue/no-unused-vars
754
+ Remove unused `v-for`/`v-slot` variables or prefix them with `_`.
755
+
756
+ ### vue/no-use-v-else-with-v-for
757
+ Do not use `v-else`/`v-else-if` on an element that also has `v-for`.
758
+
759
+ ### vue/no-use-v-if-with-v-for
760
+ Do not use `v-if` and `v-for` on the same element. Use a wrapper `<template v-for>` with `v-if` on the child.
761
+
762
+ ### vue/no-useless-template-attributes
763
+ Remove attributes on `<template>` that have no effect (only directives work on `<template>`).
764
+
765
+ ### vue/no-v-for-template-key-on-child
766
+ In Vue 3, place `key` on the `<template v-for>`, not on the child element.
767
+
768
+ ### vue/no-watch-after-await
769
+ Do not register `watch` after `await`. Move the `watch` call before any async operation.
770
+
771
+ ### vue/no-async-in-computed-properties
772
+ Do not use `async`/`await`, promises, or timers in computed properties.
773
+
774
+ ### vue/no-child-content
775
+ Do not use `v-html`/`v-text` on elements with child content — the children will be overwritten.
776
+
777
+ ### vue/no-console
778
+ Remove `console.log`/`console.warn`/`console.error` from Vue templates.
779
+
780
+ ### vue/no-constant-condition
781
+ Remove constant conditions in template `v-if`/`v-show`/`v-else-if` directives.
782
+
783
+ ### vue/no-sparse-arrays
784
+ Do not use sparse arrays (e.g., `[1, , 3]`) in templates. Use explicit `undefined` values instead (e.g., `[1, undefined, 3]`), or remove the empty slots.
785
+
786
+ ### vue/no-static-inline-styles
787
+ Do not use inline `style` attributes. Use CSS classes or `:class`/`:style` bindings.
788
+
789
+ ### vue/no-v-html
790
+ Do not use `v-html`. It is an XSS risk. Use template interpolation or `v-text` instead.
791
+
792
+ ### vue/no-v-text
793
+ Do not use `v-text`. Use mustache interpolation `{{ }}` instead.
794
+
795
+ ### vue/no-v-text-v-html-on-component
796
+ Do not use `v-text` or `v-html` on components — they overwrite slot content. Pass the content via the default slot instead (e.g., `<MyComp>content here</MyComp>`).
797
+
798
+ ### vue/prefer-true-attribute-shorthand
799
+ Use shorthand for boolean attributes: write `disabled` instead of `:disabled="true"`.
800
+
801
+ ### vue/prefer-use-template-ref
802
+ Use `useTemplateRef()` instead of `ref` attribute for template refs.
803
+
804
+ ### vue/prop-name-casing
805
+ Use `camelCase` for prop names in `<script>`.
806
+
807
+ ### vue/require-component-is
808
+ Dynamic `<component>` must have a `:is` binding.
809
+
810
+ ### vue/require-explicit-emits
811
+ Declare all emitted events in `defineEmits()`.
812
+
813
+ ### vue/require-macro-variable-name
814
+ Use the conventional variable name matching the macro: `const props = defineProps()`, `const emit = defineEmits()`, `const slots = defineSlots()`. Rename any non-standard variable names to these conventions.
815
+
816
+ ### vue/require-render-return
817
+ Render functions must return a value.
818
+
819
+ ### vue/require-toggle-inside-transition
820
+ `<transition>` content must use `v-if`, `v-show`, or dynamic components to toggle.
821
+
822
+ ### vue/require-typed-ref
823
+ Pass a type argument to `ref()` when the initial value is `null` or `undefined`.
824
+ ```ts
825
+ // Bad
826
+ const el = ref(null)
827
+ // Good
828
+ const el = ref<HTMLDivElement | null>(null)
829
+ ```
830
+
831
+ ### vue/require-v-for-key
832
+ Always provide a `:key` on elements using `v-for`.
833
+
834
+ ### vue/slot-name-casing
835
+ Use `camelCase` for slot names.
836
+
837
+ ### vue/use-v-on-exact
838
+ When an element has multiple `v-on` handlers for the same event with different modifiers (e.g., `@keyup.enter` and `@keyup`), add `.exact` to the more specific handler (e.g., `@keyup.enter.exact`) so it only fires when exactly that modifier is pressed.
839
+
840
+ ### vue/valid-attribute-name
841
+ Use valid HTML attribute names (no spaces, quotes, equals in names).
842
+
843
+ ### vue/valid-define-emits
844
+ `defineEmits()` must be at the top level of `<script setup>`, called only once, with either a runtime array (`defineEmits(['eventName'])`) or a type-only declaration (`defineEmits<{ (e: 'eventName'): void }>()`). Do not pass both runtime and type arguments.
845
+
846
+ ### vue/valid-define-options
847
+ `defineOptions()` must be at the top level of `<script setup>`, called only once, with a single object literal. It must not contain `props`, `emits`, `expose`, or `slots` — those have their own macros.
848
+
849
+ ### vue/valid-define-props
850
+ `defineProps()` must be at the top level of `<script setup>`, called only once, with either a runtime object/array or a type-only declaration (`defineProps<{ ... }>()`). Do not pass both runtime and type arguments.
851
+
852
+ ### vue/valid-template-root
853
+ The `<template>` block must not be empty and must contain valid content. In Vue 3 multiple root elements are allowed, but the template must have at least one root node. If the template is empty, add content or remove the component.
854
+
855
+ ### vue/valid-v-bind
856
+ Use valid `v-bind` directive syntax.
857
+
858
+ ### vue/valid-v-cloak
859
+ Use valid `v-cloak` directive syntax.
860
+
861
+ ### vue/valid-v-else
862
+ Use valid `v-else` directive. It must follow `v-if` or `v-else-if` and have no expression.
863
+
864
+ ### vue/valid-v-else-if
865
+ Use valid `v-else-if` directive. It must follow `v-if` or another `v-else-if`.
866
+
867
+ ### vue/valid-v-for
868
+ Use valid `v-for` syntax (e.g., `item of items`).
869
+
870
+ ### vue/valid-v-html
871
+ Use valid `v-html` directive syntax with an expression.
872
+
873
+ ### vue/valid-v-if
874
+ Use valid `v-if` directive syntax with an expression.
875
+
876
+ ### vue/valid-v-is
877
+ Use valid `v-is` directive syntax.
878
+
879
+ ### vue/valid-v-memo
880
+ Use valid `v-memo` directive with an array expression.
881
+
882
+ ### vue/valid-v-model
883
+ Use valid `v-model` directive. It must be on input elements or components, with a valid expression.
884
+
885
+ ### vue/valid-v-on
886
+ Use valid `v-on` directive syntax.
887
+
888
+ ### vue/valid-v-once
889
+ Use valid `v-once` directive. It must have no expression or argument.
890
+
891
+ ### vue/valid-v-pre
892
+ Use valid `v-pre` directive. It must have no expression or argument.
893
+
894
+ ### vue/valid-v-show
895
+ Use valid `v-show` directive syntax with an expression.
896
+
897
+ ### vue/valid-v-slot
898
+ Use valid `v-slot` directive syntax. It must be on `<template>` or a component.
899
+
900
+ ### vue/valid-v-text
901
+ Use valid `v-text` directive syntax with an expression.
902
+
903
+ ### vue/html-button-has-type
904
+ Add an explicit `type` attribute to `<button>` (`button`, `submit`, or `reset`).
905
+
906
+ ## RxJS
907
+
908
+ ### rxjs/no-compat
909
+ Do not import from `rxjs/Rx` or `rxjs-compat`. Use direct imports from `rxjs` and `rxjs/operators`.
910
+
911
+ ### rxjs/no-create
912
+ Do not use `Observable.create()`. Use `new Observable()` or creation operators (`of`, `from`, etc.).
913
+
914
+ ### rxjs/no-ignored-error
915
+ Do not call `.subscribe()` without an error handler. Either pass an observer object with an `error` callback (e.g., `.subscribe({ next: val => …, error: err => … })`) or pipe through `catchError` before subscribing.
916
+
917
+ ### rxjs/no-ignored-observable
918
+ Do not ignore returned Observables. Either `.subscribe()` to the returned Observable, or assign it to a variable for later use. If the result is intentionally unused, pipe through `tap()` for side effects or remove the call entirely.
919
+
920
+ ### rxjs/no-ignored-replay-buffer
921
+ Provide a `bufferSize` argument to `ReplaySubject`. The default is `Infinity`.
922
+
923
+ ### rxjs/no-ignored-subscribe
924
+ Do not call `.subscribe()` without providing at least a next handler.
925
+
926
+ ### rxjs/no-ignored-subscription
927
+ Assign the return value of `.subscribe()` to a variable (e.g., `const sub = obs$.subscribe(…)`) and call `sub.unsubscribe()` during cleanup (e.g., in `ngOnDestroy` or a teardown function). Alternatively, use `takeUntil(destroy$)` before `.subscribe()` to manage the lifecycle declaratively.
928
+
929
+ ### rxjs/no-index
930
+ Do not import from `rxjs/index`. Import directly from `rxjs`.
931
+
932
+ ### rxjs/no-topromise
933
+ Do not use `.toPromise()`. Use `firstValueFrom()` or `lastValueFrom()`.
934
+
935
+ ### rxjs/no-unbound-methods
936
+ Bind methods before passing them as observer callbacks, or use arrow functions.
937
+
938
+ ### rxjs/finnish
939
+ Observable variables and parameters must use the `$` suffix (`data$`, `click$`).
940
+
941
+ ### rxjs/no-async-subscribe
942
+ Do not pass `async` functions to `.subscribe()`. Errors inside async subscribe are silently lost.
943
+
944
+ ### rxjs/no-cyclic-action
945
+ Do not create actions that re-emit themselves, creating infinite loops in effects.
946
+
947
+ ### rxjs/no-exposed-subjects
948
+ Do not expose `Subject` directly. Expose as `Observable` using `.asObservable()`.
949
+
950
+ ### rxjs/no-ignored-notifier
951
+ Use the `notifications` parameter passed to `repeatWhen`/`retryWhen` to control retry/repeat timing (e.g., `retryWhen(errors => errors.pipe(delay(1000)))`). If you don't need conditional logic, use `retry({ delay: 1000 })` or `repeat({ delay: 1000 })` instead.
952
+
953
+ ### rxjs/no-ignored-takewhile-value
954
+ Use the value parameter in `takeWhile` callbacks. If unused, use `take` instead.
955
+
956
+ ### rxjs/no-redundant-notify
957
+ Do not call `next()` immediately before `complete()` or `error()` when the `next` value is unused downstream. Remove the redundant `next()` call and keep only `complete()` (or `error()`). If the value from `next()` is needed by subscribers, that is fine — the rule flags cases where `next()` has no effect because the stream terminates immediately after.
958
+
959
+ ### rxjs/no-subclass
960
+ Do not subclass RxJS classes (Observable, Subject, etc.). Instead of `class MyObs extends Observable`, create a plain class that holds an Observable as a property or exposes one via a factory function that pipes creation operators and custom operators together.
961
+
962
+ ### rxjs/no-subject-unsubscribe
963
+ Do not call `.unsubscribe()` on subjects. Unsubscribe from the subscription instead.
964
+
965
+ ### rxjs/no-subject-value
966
+ Do not access `.value` on `BehaviorSubject`. Subscribe or use `getValue()` explicitly if necessary.
967
+
968
+ ### rxjs/no-unsafe-catch
969
+ Place `catchError` inside `switchMap`/`mergeMap`/etc., not outside — an error outside kills the outer stream.
970
+
971
+ ### rxjs/no-unsafe-first
972
+ Use `take(1)` inside `switchMap`/`mergeMap`/etc. instead of `first()` — `first()` errors on empty streams.
973
+
974
+ ### rxjs/no-unsafe-subject-next
975
+ Do not call `.next()` on a subject inside an operator that may not reach it (e.g., after `takeUntil`).
976
+
977
+ ### rxjs/no-unsafe-takeuntil
978
+ Place `takeUntil` as the last operator before `subscribe` to avoid subscription leaks.
979
+
980
+ ### rxjs/suffix-subjects
981
+ Subject variables must use the `Subject` suffix (e.g., `clickSubject`, `dataSubject`).
982
+
983
+ ### rxjs/throw-error
984
+ Only throw `Error` objects in `throwError()`. Do not throw strings or plain objects.
985
+
986
+ ### rxjs/no-connectable
987
+ Do not use connectable observables. Use `share`, `shareReplay`, or `publish` operators.
988
+
989
+ ### rxjs/no-nested-subscribe
990
+ Do not nest `.subscribe()` calls. Use `switchMap`, `mergeMap`, `concatMap`, or `exhaustMap`.
991
+
992
+ ### rxjs/no-sharereplay
993
+ Use `shareReplay` with `{ refCount: true }` to avoid memory leaks.
994
+
995
+ ### rxjs/no-subscribe-handlers
996
+ Use the observer object form `{ next, error, complete }` instead of positional arguments in `.subscribe()`.
997
+
998
+ ### rxjs/no-unsafe-switchmap
999
+ Do not use `switchMap` with actions that should not be cancelled (e.g., writes/deletes). Use `concatMap` or `mergeMap`.
1000
+
1001
+ ## JSDoc
1002
+
1003
+ ### jsdoc/no-bad-blocks
1004
+ Use `/** ... */` for JSDoc comments, not `/* ... */`.
1005
+
1006
+ ### jsdoc/require-jsdoc
1007
+ Add JSDoc comments to public APIs: type aliases, interfaces, enums, class declarations, method definitions, arrow functions at module level, object expressions, and property definitions. Analyze what each part of the code does from the perspective of public use and create a concise but comprehensive JSDoc description based on this analysis.
1008
+
1009
+ ## Boundaries (FSD)
1010
+
1011
+ ### boundaries/element-types
1012
+ Follow Feature Sliced Design import rules:
1013
+ - **shared** must not import from `entities`, `features`, `widgets`, `pages`, `app`
1014
+ - **entities** must not import from `features`, `widgets`, `pages`, `app` or other entities
1015
+ - **features** must not import from `widgets`, `pages`, `app` or other features
1016
+ - **widgets** must not import from `pages`, `app` or other widgets
1017
+ - **pages** must not import from `app` or other pages
1018
+
1019
+ Move the imported code to a shared layer or pass it as a dependency.
1020
+
1021
+ ### boundaries/entry-point
1022
+ Import only from public API entry points. Non-shared layers (`entities`, `features`, `widgets`, `pages`, `app`) must be imported through `index.ts` or `index.vue`. Shared layer allows any entry point. If the required index.ts file doesn't exist - you must create it in it's respective segment (the root of an entity/feature/etc)
1023
+
1024
+ ## Productive
1025
+
1026
+ ### productive/no-abusive-nested-if
1027
+ Reduce `if` nesting to 2 levels or below. Use early returns, guard clauses, or extract nested conditions into separate functions.
1028
+
1029
+ ### productive/no-else
1030
+ Remove `else`/`else if` blocks. Use early returns or omit the else entirely.
1031
+ ```ts
1032
+ // Bad
1033
+ return condition ? a : b;
1034
+ // Good
1035
+ if (condition) {
1036
+ return a
1037
+ }
1038
+ return b
1039
+ ```