@codelaw/rules-js 0.0.0-stage → 0.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.
Files changed (162) hide show
  1. package/LICENSE +23 -0
  2. package/NOTICE +19 -0
  3. package/README.md +90 -2
  4. package/codelaw-pack.toml +6 -0
  5. package/data/globals/browser.json +1209 -0
  6. package/data/globals/commonjs.json +6 -0
  7. package/data/globals/jest.json +15 -0
  8. package/data/globals/mocha.json +22 -0
  9. package/data/globals/node.json +83 -0
  10. package/data/globals/serviceworker.json +328 -0
  11. package/data/globals/shared-node-browser.json +73 -0
  12. package/data/globals/vitest.json +19 -0
  13. package/data/globals/worker.json +349 -0
  14. package/data/node/deprecated-api.json +83 -0
  15. package/data/react/dom-property-aliases.json +131 -0
  16. package/package.json +14 -4
  17. package/presets/js/conventions.toml +10 -0
  18. package/presets/js/recommended.toml +67 -0
  19. package/presets/node/recommended.toml +13 -0
  20. package/presets/react/recommended.toml +22 -0
  21. package/presets/stencil/recommended.toml +18 -0
  22. package/presets/ts/recommended.toml +27 -0
  23. package/rules/graph/no-unused-exports.md +135 -0
  24. package/rules/js/constructor-super.md +77 -0
  25. package/rules/js/exports-at-end.md +134 -0
  26. package/rules/js/for-direction.md +106 -0
  27. package/rules/js/getter-return.md +74 -0
  28. package/rules/js/import-groups.md +117 -0
  29. package/rules/js/no-async-promise-executor.md +95 -0
  30. package/rules/js/no-case-declarations.md +134 -0
  31. package/rules/js/no-class-assign.md +61 -0
  32. package/rules/js/no-compare-neg-zero.md +105 -0
  33. package/rules/js/no-cond-assign.md +135 -0
  34. package/rules/js/no-const-assign.md +61 -0
  35. package/rules/js/no-constant-binary-expression.md +83 -0
  36. package/rules/js/no-constant-condition.md +150 -0
  37. package/rules/js/no-control-regex.md +84 -0
  38. package/rules/js/no-debugger.md +99 -0
  39. package/rules/js/no-default-export.md +88 -0
  40. package/rules/js/no-delete-var.md +93 -0
  41. package/rules/js/no-dupe-args.md +61 -0
  42. package/rules/js/no-dupe-class-members.md +82 -0
  43. package/rules/js/no-dupe-else-if.md +113 -0
  44. package/rules/js/no-dupe-keys.md +66 -0
  45. package/rules/js/no-duplicate-case.md +137 -0
  46. package/rules/js/no-empty-character-class.md +98 -0
  47. package/rules/js/no-empty-pattern.md +86 -0
  48. package/rules/js/no-empty-static-block.md +99 -0
  49. package/rules/js/no-empty.md +116 -0
  50. package/rules/js/no-ex-assign.md +121 -0
  51. package/rules/js/no-extra-boolean-cast.md +107 -0
  52. package/rules/js/no-fallthrough.md +178 -0
  53. package/rules/js/no-func-assign.md +62 -0
  54. package/rules/js/no-global-assign.md +85 -0
  55. package/rules/js/no-import-assign.md +60 -0
  56. package/rules/js/no-invalid-regexp.md +86 -0
  57. package/rules/js/no-irregular-whitespace.md +87 -0
  58. package/rules/js/no-loss-of-precision.md +82 -0
  59. package/rules/js/no-misleading-character-class.md +83 -0
  60. package/rules/js/no-new-native-nonconstructor.md +55 -0
  61. package/rules/js/no-nonoctal-decimal-escape.md +84 -0
  62. package/rules/js/no-obj-calls.md +61 -0
  63. package/rules/js/no-octal.md +84 -0
  64. package/rules/js/no-prototype-builtins.md +99 -0
  65. package/rules/js/no-redeclare.md +61 -0
  66. package/rules/js/no-regex-spaces.md +75 -0
  67. package/rules/js/no-self-assign.md +91 -0
  68. package/rules/js/no-setter-return.md +69 -0
  69. package/rules/js/no-shadow-restricted-names.md +102 -0
  70. package/rules/js/no-sparse-arrays.md +82 -0
  71. package/rules/js/no-this-before-super.md +74 -0
  72. package/rules/js/no-unassigned-vars.md +102 -0
  73. package/rules/js/no-undef.md +76 -0
  74. package/rules/js/no-unexpected-multiline.md +91 -0
  75. package/rules/js/no-unreachable.md +59 -0
  76. package/rules/js/no-unsafe-finally.md +145 -0
  77. package/rules/js/no-unsafe-negation.md +71 -0
  78. package/rules/js/no-unsafe-optional-chaining.md +83 -0
  79. package/rules/js/no-unused-labels.md +102 -0
  80. package/rules/js/no-unused-private-class-members.md +126 -0
  81. package/rules/js/no-unused-vars.md +69 -0
  82. package/rules/js/no-useless-assignment.md +115 -0
  83. package/rules/js/no-useless-backreference.md +83 -0
  84. package/rules/js/no-useless-catch.md +105 -0
  85. package/rules/js/no-useless-escape.md +81 -0
  86. package/rules/js/no-var.md +76 -0
  87. package/rules/js/no-with.md +60 -0
  88. package/rules/js/prefer-const.md +83 -0
  89. package/rules/js/prefer-rest-params.md +103 -0
  90. package/rules/js/prefer-spread.md +95 -0
  91. package/rules/js/preserve-caught-error.md +122 -0
  92. package/rules/js/require-yield.md +107 -0
  93. package/rules/js/use-isnan.md +105 -0
  94. package/rules/js/valid-typeof.md +111 -0
  95. package/rules/node/hashbang.md +71 -0
  96. package/rules/node/no-deprecated-api.md +91 -0
  97. package/rules/node/no-exports-assign.md +92 -0
  98. package/rules/node/no-extraneous-import.md +118 -0
  99. package/rules/node/no-extraneous-require.md +117 -0
  100. package/rules/node/no-missing-import.md +118 -0
  101. package/rules/node/no-missing-require.md +117 -0
  102. package/rules/node/no-process-exit.md +99 -0
  103. package/rules/node/no-unpublished-import.md +134 -0
  104. package/rules/node/no-unpublished-require.md +133 -0
  105. package/rules/react/display-name.md +91 -0
  106. package/rules/react/exhaustive-deps.md +116 -0
  107. package/rules/react/hook-prefix.md +108 -0
  108. package/rules/react/jsx-key.md +99 -0
  109. package/rules/react/jsx-no-comment-textnodes.md +87 -0
  110. package/rules/react/jsx-no-duplicate-props.md +66 -0
  111. package/rules/react/jsx-no-target-blank.md +78 -0
  112. package/rules/react/jsx-no-undef.md +78 -0
  113. package/rules/react/no-children-prop.md +80 -0
  114. package/rules/react/no-danger-with-children.md +83 -0
  115. package/rules/react/no-deprecated.md +84 -0
  116. package/rules/react/no-direct-mutation-state.md +102 -0
  117. package/rules/react/no-find-dom-node.md +72 -0
  118. package/rules/react/no-is-mounted.md +109 -0
  119. package/rules/react/no-render-return-value.md +75 -0
  120. package/rules/react/no-string-refs.md +72 -0
  121. package/rules/react/no-unescaped-entities.md +69 -0
  122. package/rules/react/no-unknown-property.md +69 -0
  123. package/rules/react/props-type-name.md +43 -0
  124. package/rules/react/require-render-return.md +91 -0
  125. package/rules/react/rules-of-hooks.md +128 -0
  126. package/rules/stencil/ban-default-true.md +70 -0
  127. package/rules/stencil/ban-exported-const-enums.md +60 -0
  128. package/rules/stencil/ban-prefix.md +76 -0
  129. package/rules/stencil/decorators-context.md +61 -0
  130. package/rules/stencil/host-data-deprecated.md +73 -0
  131. package/rules/stencil/methods-must-be-public.md +69 -0
  132. package/rules/stencil/no-unused-watch.md +68 -0
  133. package/rules/stencil/own-methods-must-be-private.md +68 -0
  134. package/rules/stencil/own-props-must-be-private.md +60 -0
  135. package/rules/stencil/prefer-vdom-listener.md +67 -0
  136. package/rules/stencil/prop-readonly.md +63 -0
  137. package/rules/stencil/props-must-be-public.md +68 -0
  138. package/rules/stencil/required-jsdoc.md +66 -0
  139. package/rules/stencil/reserved-member-names.md +70 -0
  140. package/rules/stencil/strict-mutable.md +75 -0
  141. package/rules/stencil/tag-prefix.md +75 -0
  142. package/rules/ts/ban-ts-comment.md +64 -0
  143. package/rules/ts/no-array-constructor.md +58 -0
  144. package/rules/ts/no-duplicate-enum-values.md +65 -0
  145. package/rules/ts/no-empty-object-type.md +65 -0
  146. package/rules/ts/no-explicit-any.md +61 -0
  147. package/rules/ts/no-extra-non-null-assertion.md +50 -0
  148. package/rules/ts/no-misused-new.md +70 -0
  149. package/rules/ts/no-namespace.md +65 -0
  150. package/rules/ts/no-non-null-asserted-optional-chain.md +55 -0
  151. package/rules/ts/no-require-imports.md +54 -0
  152. package/rules/ts/no-this-alias.md +68 -0
  153. package/rules/ts/no-unnecessary-type-constraint.md +64 -0
  154. package/rules/ts/no-unsafe-declaration-merging.md +73 -0
  155. package/rules/ts/no-unsafe-function-type.md +57 -0
  156. package/rules/ts/no-unused-expressions.md +61 -0
  157. package/rules/ts/no-unused-vars.md +68 -0
  158. package/rules/ts/no-wrapper-object-types.md +49 -0
  159. package/rules/ts/prefer-as-const.md +47 -0
  160. package/rules/ts/prefer-namespace-keyword.md +63 -0
  161. package/rules/ts/triple-slash-reference.md +60 -0
  162. package/rules/ts/type-only-imports.md +57 -0
@@ -0,0 +1,95 @@
1
+ ---
2
+ id: js/no-async-promise-executor
3
+ title: "A Promise executor is not an async function"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the rewrite depends on what the executor does"
7
+ stability: preview
8
+ ported_from: [eslint/no-async-promise-executor]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The function passed to `new Promise(...)` is not `async`.
13
+
14
+ **Why:** An error thrown in an async executor doesn't reject the promise, and an executor that needs
15
+ `await` doesn't need the `Promise` wrapper.
16
+
17
+ ```codelaw
18
+ match:
19
+ any:
20
+ - pattern: new Promise(async ($$$P) => $$$B)
21
+ - pattern: new Promise(async function ($$$P) { $$$B })
22
+ - pattern: new Promise(async $P => $$$B)
23
+ message: "An async Promise executor loses its errors; await inside a plain async function instead"
24
+ ```
25
+
26
+ ## How to fix
27
+
28
+ 1. If the executor only awaits and resolves, use the awaited promise directly.
29
+ 2. Otherwise make the executor a plain function and handle errors with `reject`.
30
+
31
+ ## Examples
32
+
33
+ ### JavaScript
34
+
35
+ #### Don't
36
+
37
+ ```js
38
+ const data = new Promise(async (resolve) => {
39
+ resolve(await load());
40
+ });
41
+ ```
42
+
43
+ #### Do
44
+
45
+ ```js
46
+ const data = load();
47
+ ```
48
+
49
+ ### JSX
50
+
51
+ #### Don't
52
+
53
+ ```jsx
54
+ const data = new Promise(async (resolve) => {
55
+ resolve(await load());
56
+ });
57
+ ```
58
+
59
+ #### Do
60
+
61
+ ```jsx
62
+ const data = load();
63
+ ```
64
+
65
+ ### TypeScript
66
+
67
+ #### Don't
68
+
69
+ ```ts
70
+ const data = new Promise(async (resolve) => {
71
+ resolve(await load());
72
+ });
73
+ ```
74
+
75
+ #### Do
76
+
77
+ ```ts
78
+ const data = load();
79
+ ```
80
+
81
+ ### TSX
82
+
83
+ #### Don't
84
+
85
+ ```tsx
86
+ const data = new Promise(async (resolve) => {
87
+ resolve(await load());
88
+ });
89
+ ```
90
+
91
+ #### Do
92
+
93
+ ```tsx
94
+ const data = load();
95
+ ```
@@ -0,0 +1,134 @@
1
+ ---
2
+ id: js/no-case-declarations
3
+ title: "No let, const, function or class directly in a case"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "another case may rely on the shared declaration"
7
+ stability: preview
8
+ ported_from: [eslint/no-case-declarations]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ A `let`, `const`, `function` or `class` inside a `case` sits in a block `{ … }` of its own.
13
+
14
+ **Why:** Declarations in a case are scoped to the whole `switch`, so another case can see them
15
+ uninitialised.
16
+
17
+ ```codelaw
18
+ match:
19
+ any:
20
+ - kind: lexical_declaration
21
+ - kind: class_declaration
22
+ - kind: function_declaration
23
+ inside:
24
+ stopBy: neighbor
25
+ any: [{ kind: switch_case }, { kind: switch_default }]
26
+ message: "A declaration in a case is visible to the whole switch; wrap the case in braces"
27
+ ```
28
+
29
+ ## How to fix
30
+
31
+ 1. Wrap the case's statements in `{ … }`.
32
+ 2. If another case uses the declaration, move it above the `switch`.
33
+
34
+ ## Examples
35
+
36
+ ### JavaScript
37
+
38
+ #### Don't
39
+
40
+ ```js
41
+ switch (kind) {
42
+ case "a":
43
+ const n = 1;
44
+ use(n);
45
+ break;
46
+ }
47
+ ```
48
+
49
+ #### Do
50
+
51
+ ```js
52
+ switch (kind) {
53
+ case "a": {
54
+ const n = 1;
55
+ use(n);
56
+ break;
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### JSX
62
+
63
+ #### Don't
64
+
65
+ ```jsx
66
+ switch (kind) {
67
+ case "a":
68
+ const n = 1;
69
+ use(n);
70
+ break;
71
+ }
72
+ ```
73
+
74
+ #### Do
75
+
76
+ ```jsx
77
+ switch (kind) {
78
+ case "a": {
79
+ const n = 1;
80
+ use(n);
81
+ break;
82
+ }
83
+ }
84
+ ```
85
+
86
+ ### TypeScript
87
+
88
+ #### Don't
89
+
90
+ ```ts
91
+ switch (kind) {
92
+ case "a":
93
+ const n = 1;
94
+ use(n);
95
+ break;
96
+ }
97
+ ```
98
+
99
+ #### Do
100
+
101
+ ```ts
102
+ switch (kind) {
103
+ case "a": {
104
+ const n = 1;
105
+ use(n);
106
+ break;
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### TSX
112
+
113
+ #### Don't
114
+
115
+ ```tsx
116
+ switch (kind) {
117
+ case "a":
118
+ const n = 1;
119
+ use(n);
120
+ break;
121
+ }
122
+ ```
123
+
124
+ #### Do
125
+
126
+ ```tsx
127
+ switch (kind) {
128
+ case "a": {
129
+ const n = 1;
130
+ use(n);
131
+ break;
132
+ }
133
+ }
134
+ ```
@@ -0,0 +1,61 @@
1
+ ---
2
+ id: js/no-class-assign
3
+ title: "A class name is not reassigned"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "what the assignment was for is the author's call"
7
+ stability: preview
8
+ ported_from: [eslint/no-class-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign a new value to the name a class declaration binds.
13
+
14
+ **Why:** Reassigning a class name is almost always a mistake, and makes every later use mean
15
+ something else.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: identifier
20
+ where:
21
+ $$MATCH: [write, { binding: class }]
22
+ message: "`$$MATCH` is a class; don't assign to it"
23
+ ```
24
+
25
+ ## How to fix
26
+
27
+ 1. Assign to a new variable instead of the class name.
28
+
29
+ ## Examples
30
+
31
+ ### JavaScript
32
+
33
+ #### Don't
34
+
35
+ ```js
36
+ class Point {}
37
+ Point = null;
38
+ ```
39
+
40
+ #### Do
41
+
42
+ ```js
43
+ class Point {}
44
+ const origin = null;
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ class Point {}
53
+ Point = null;
54
+ ```
55
+
56
+ #### Do
57
+
58
+ ```jsx
59
+ class Point {}
60
+ const origin = null;
61
+ ```
@@ -0,0 +1,105 @@
1
+ ---
2
+ id: js/no-compare-neg-zero
3
+ title: "No comparisons against -0"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether `0` or `-0` was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-compare-neg-zero]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't compare a value with `-0` using `==`, `===`, `<` or the other comparison operators.
13
+
14
+ **Why:** These operators treat `-0` and `0` as equal, so the comparison doesn't test what it says.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: binary_expression
19
+ any:
20
+ - has: { field: right, pattern: "-0" }
21
+ - has: { field: left, pattern: "-0" }
22
+ has:
23
+ field: operator
24
+ regex: ^(==|===|!=|!==|<|>|<=|>=)$
25
+ message: "Comparing with -0 is the same as comparing with 0; use Object.is(x, -0) to test for -0"
26
+ ```
27
+
28
+ ## How to fix
29
+
30
+ 1. To test for negative zero, use `Object.is(x, -0)`.
31
+ 2. To test for zero of either sign, compare with `0`.
32
+
33
+ ## Examples
34
+
35
+ ### JavaScript
36
+
37
+ #### Don't
38
+
39
+ ```js
40
+ if (x === -0) {
41
+ flip();
42
+ }
43
+ ```
44
+
45
+ #### Do
46
+
47
+ ```js
48
+ if (Object.is(x, -0)) {
49
+ flip();
50
+ }
51
+ ```
52
+
53
+ ### JSX
54
+
55
+ #### Don't
56
+
57
+ ```jsx
58
+ if (x === -0) {
59
+ flip();
60
+ }
61
+ ```
62
+
63
+ #### Do
64
+
65
+ ```jsx
66
+ if (Object.is(x, -0)) {
67
+ flip();
68
+ }
69
+ ```
70
+
71
+ ### TypeScript
72
+
73
+ #### Don't
74
+
75
+ ```ts
76
+ if (x === -0) {
77
+ flip();
78
+ }
79
+ ```
80
+
81
+ #### Do
82
+
83
+ ```ts
84
+ if (Object.is(x, -0)) {
85
+ flip();
86
+ }
87
+ ```
88
+
89
+ ### TSX
90
+
91
+ #### Don't
92
+
93
+ ```tsx
94
+ if (x === -0) {
95
+ flip();
96
+ }
97
+ ```
98
+
99
+ #### Do
100
+
101
+ ```tsx
102
+ if (Object.is(x, -0)) {
103
+ flip();
104
+ }
105
+ ```
@@ -0,0 +1,135 @@
1
+ ---
2
+ id: js/no-cond-assign
3
+ title: "No assignment in a condition, unless doubly parenthesised"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "whether a comparison or an assignment was meant needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-cond-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The condition of an `if`, `while`, `do … while` or `for` is not an assignment, unless it is wrapped
13
+ in a second pair of parentheses to say it's meant.
14
+
15
+ **Why:** `if (a = b)` assigns and tests the result, which is almost always a mistyped `===`.
16
+
17
+ ```codelaw
18
+ match:
19
+ kind: assignment_expression
20
+ any:
21
+ - inside:
22
+ stopBy: neighbor
23
+ kind: parenthesized_expression
24
+ inside:
25
+ stopBy: neighbor
26
+ any: [{ kind: if_statement }, { kind: while_statement }, { kind: do_statement }]
27
+ - inside:
28
+ stopBy: neighbor
29
+ kind: expression_statement
30
+ inside: { stopBy: neighbor, kind: for_statement, field: condition }
31
+ message: "An assignment in a condition is usually a mistyped comparison"
32
+ ```
33
+
34
+ ## How to fix
35
+
36
+ 1. If a comparison was meant, use `===`.
37
+ 2. If the assignment is meant, wrap it in a second pair of parentheses.
38
+
39
+ ## Examples
40
+
41
+ ### JavaScript
42
+
43
+ #### Don't
44
+
45
+ ```js
46
+ if (user = admin) {
47
+ grant();
48
+ }
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```js
54
+ if (user === admin) {
55
+ grant();
56
+ }
57
+ ```
58
+
59
+ ```js
60
+ while ((node = node.next)) {
61
+ visit(node);
62
+ }
63
+ ```
64
+
65
+ ### JSX
66
+
67
+ #### Don't
68
+
69
+ ```jsx
70
+ if (user = admin) {
71
+ grant();
72
+ }
73
+ ```
74
+
75
+ #### Do
76
+
77
+ ```jsx
78
+ if (user === admin) {
79
+ grant();
80
+ }
81
+ ```
82
+
83
+ ```jsx
84
+ while ((node = node.next)) {
85
+ visit(node);
86
+ }
87
+ ```
88
+
89
+ ### TypeScript
90
+
91
+ #### Don't
92
+
93
+ ```ts
94
+ if (user = admin) {
95
+ grant();
96
+ }
97
+ ```
98
+
99
+ #### Do
100
+
101
+ ```ts
102
+ if (user === admin) {
103
+ grant();
104
+ }
105
+ ```
106
+
107
+ ```ts
108
+ while ((node = node.next)) {
109
+ visit(node);
110
+ }
111
+ ```
112
+
113
+ ### TSX
114
+
115
+ #### Don't
116
+
117
+ ```tsx
118
+ if (user = admin) {
119
+ grant();
120
+ }
121
+ ```
122
+
123
+ #### Do
124
+
125
+ ```tsx
126
+ if (user === admin) {
127
+ grant();
128
+ }
129
+ ```
130
+
131
+ ```tsx
132
+ while ((node = node.next)) {
133
+ visit(node);
134
+ }
135
+ ```
@@ -0,0 +1,61 @@
1
+ ---
2
+ id: js/no-const-assign
3
+ title: "A const is not reassigned"
4
+ languages: [javascript, jsx]
5
+ fix: manual
6
+ fix_reason: "whether the variable should be `let` or the assignment should go is the author's call"
7
+ stability: preview
8
+ ported_from: [eslint/no-const-assign]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ Code doesn't assign a new value to a `const`.
13
+
14
+ **Why:** Assigning to a `const` throws a TypeError at run time.
15
+
16
+ ```codelaw
17
+ match:
18
+ kind: identifier
19
+ where:
20
+ $$MATCH: [write, { binding: const }]
21
+ message: "`$$MATCH` is a const; assigning to it throws"
22
+ ```
23
+
24
+ ## How to fix
25
+
26
+ 1. If the value is meant to change, declare it with `let`.
27
+ 2. Otherwise assign to a new variable.
28
+
29
+ ## Examples
30
+
31
+ ### JavaScript
32
+
33
+ #### Don't
34
+
35
+ ```js
36
+ const total = 0;
37
+ total = 1;
38
+ ```
39
+
40
+ #### Do
41
+
42
+ ```js
43
+ let total = 0;
44
+ total = 1;
45
+ ```
46
+
47
+ ### JSX
48
+
49
+ #### Don't
50
+
51
+ ```jsx
52
+ const total = 0;
53
+ total = 1;
54
+ ```
55
+
56
+ #### Do
57
+
58
+ ```jsx
59
+ let total = 0;
60
+ total = 1;
61
+ ```
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: js/no-constant-binary-expression
3
+ title: "No binary expression whose result is fixed"
4
+ languages: [javascript, jsx, typescript, tsx]
5
+ fix: manual
6
+ fix_reason: "the intended grouping or comparison needs the author"
7
+ stability: preview
8
+ ported_from: [eslint/no-constant-binary-expression]
9
+ since: 0.1.0
10
+ ---
11
+
12
+ The left side of `??`, `||` and `&&` is not a value whose nullishness or truthiness is fixed, and
13
+ nothing is compared with a newly created object or with `null` when it can never be `null`.
14
+
15
+ **Why:** Such an expression always gives the same answer, which usually means the author misread
16
+ operator precedence.
17
+
18
+ ```codelaw
19
+ native: js/no-constant-binary-expression
20
+ ```
21
+
22
+ ## How to fix
23
+
24
+ 1. Add the parentheses the expression was meant to have.
25
+ 2. Or compare with the value that was meant.
26
+
27
+ ## Examples
28
+
29
+ ### JavaScript
30
+
31
+ #### Don't
32
+
33
+ ```js
34
+ const total = price + tax ?? 0;
35
+ ```
36
+
37
+ #### Do
38
+
39
+ ```js
40
+ const total = price + (tax ?? 0);
41
+ ```
42
+
43
+ ### JSX
44
+
45
+ #### Don't
46
+
47
+ ```jsx
48
+ const total = price + tax ?? 0;
49
+ ```
50
+
51
+ #### Do
52
+
53
+ ```jsx
54
+ const total = price + (tax ?? 0);
55
+ ```
56
+
57
+ ### TypeScript
58
+
59
+ #### Don't
60
+
61
+ ```ts
62
+ const total = price + tax ?? 0;
63
+ ```
64
+
65
+ #### Do
66
+
67
+ ```ts
68
+ const total = price + (tax ?? 0);
69
+ ```
70
+
71
+ ### TSX
72
+
73
+ #### Don't
74
+
75
+ ```tsx
76
+ const total = price + tax ?? 0;
77
+ ```
78
+
79
+ #### Do
80
+
81
+ ```tsx
82
+ const total = price + (tax ?? 0);
83
+ ```