@typescript-eslint/eslint-plugin 8.50.2-alpha.14 → 8.50.2-alpha.16

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/dist/index.d.ts CHANGED
@@ -988,7 +988,7 @@ declare const _default: {
988
988
  'no-useless-constructor': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noUselessConstructor" | "removeConstructor", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
989
989
  name: string;
990
990
  };
991
- 'no-useless-default-assignment': import("@typescript-eslint/utils/ts-eslint").RuleModule<"uselessDefaultAssignment" | "uselessUndefined", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
991
+ 'no-useless-default-assignment': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferOptionalSyntax" | "uselessDefaultAssignment" | "uselessUndefined", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
992
992
  name: string;
993
993
  };
994
994
  'no-useless-empty-export': import("@typescript-eslint/utils/ts-eslint").RuleModule<"uselessExport", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
@@ -1011,7 +1011,7 @@ declare const _default: {
1011
1011
  'no-useless-constructor': TSESLint.RuleModule<"noUselessConstructor" | "removeConstructor", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
1012
1012
  name: string;
1013
1013
  };
1014
- 'no-useless-default-assignment': TSESLint.RuleModule<"uselessDefaultAssignment" | "uselessUndefined", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
1014
+ 'no-useless-default-assignment': TSESLint.RuleModule<"preferOptionalSyntax" | "uselessDefaultAssignment" | "uselessUndefined", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
1015
1015
  name: string;
1016
1016
  };
1017
1017
  'no-useless-empty-export': TSESLint.RuleModule<"uselessExport", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
@@ -312,7 +312,7 @@ declare const rules: {
312
312
  'no-useless-constructor': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noUselessConstructor" | "removeConstructor", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
313
313
  name: string;
314
314
  };
315
- 'no-useless-default-assignment': import("@typescript-eslint/utils/ts-eslint").RuleModule<"uselessDefaultAssignment" | "uselessUndefined", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
315
+ 'no-useless-default-assignment': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferOptionalSyntax" | "uselessDefaultAssignment" | "uselessUndefined", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
316
316
  name: string;
317
317
  };
318
318
  'no-useless-empty-export': import("@typescript-eslint/utils/ts-eslint").RuleModule<"uselessExport", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
@@ -1,5 +1,6 @@
1
- type MessageId = 'uselessDefaultAssignment' | 'uselessUndefined';
2
- declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageId, [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ type MessageId = 'preferOptionalSyntax' | 'uselessDefaultAssignment' | 'uselessUndefined';
3
+ declare const _default: TSESLint.RuleModule<MessageId, [], import("../../rules").ESLintPluginDocs, TSESLint.RuleListener> & {
3
4
  name: string;
4
5
  };
5
6
  export default _default;
@@ -48,6 +48,7 @@ exports.default = (0, util_1.createRule)({
48
48
  },
49
49
  fixable: 'code',
50
50
  messages: {
51
+ preferOptionalSyntax: 'Using `= undefined` to make a parameter optional adds unnecessary runtime logic. Use the `?` optional syntax instead.',
51
52
  uselessDefaultAssignment: 'Default value is useless because the {{ type }} is not optional.',
52
53
  uselessUndefined: 'Default value is useless because it is undefined. Optional {{ type }}s are already undefined by default.',
53
54
  },
@@ -84,11 +85,18 @@ exports.default = (0, util_1.createRule)({
84
85
  function checkAssignmentPattern(node) {
85
86
  if (node.right.type === utils_1.AST_NODE_TYPES.Identifier &&
86
87
  node.right.name === 'undefined') {
88
+ const tsNode = services.esTreeNodeToTSNodeMap.get(node);
89
+ if (ts.isParameter(tsNode) &&
90
+ tsNode.type &&
91
+ canBeUndefined(checker.getTypeFromTypeNode(tsNode.type))) {
92
+ reportPreferOptionalSyntax(node);
93
+ return;
94
+ }
87
95
  const type = node.parent.type === utils_1.AST_NODE_TYPES.Property ||
88
96
  node.parent.type === utils_1.AST_NODE_TYPES.ArrayPattern
89
97
  ? 'property'
90
98
  : 'parameter';
91
- reportUselessDefault(node, type, 'uselessUndefined');
99
+ reportUselessUndefined(node, type);
92
100
  return;
93
101
  }
94
102
  const parent = node.parent;
@@ -113,7 +121,7 @@ exports.default = (0, util_1.createRule)({
113
121
  if ((paramSymbol.flags & ts.SymbolFlags.Optional) === 0) {
114
122
  const paramType = checker.getTypeOfSymbol(paramSymbol);
115
123
  if (!canBeUndefined(paramType)) {
116
- reportUselessDefault(node, 'parameter', 'uselessDefaultAssignment');
124
+ reportUselessDefaultAssignment(node, 'parameter');
117
125
  }
118
126
  }
119
127
  }
@@ -127,7 +135,7 @@ exports.default = (0, util_1.createRule)({
127
135
  return;
128
136
  }
129
137
  if (!canBeUndefined(propertyType)) {
130
- reportUselessDefault(node, 'property', 'uselessDefaultAssignment');
138
+ reportUselessDefaultAssignment(node, 'property');
131
139
  }
132
140
  }
133
141
  else if (parent.type === utils_1.AST_NODE_TYPES.ArrayPattern) {
@@ -145,7 +153,7 @@ exports.default = (0, util_1.createRule)({
145
153
  }
146
154
  const elementType = tupleArgs[elementIndex];
147
155
  if (!canBeUndefined(elementType)) {
148
- reportUselessDefault(node, 'property', 'uselessDefaultAssignment');
156
+ reportUselessDefaultAssignment(node, 'property');
149
157
  }
150
158
  }
151
159
  }
@@ -201,20 +209,40 @@ exports.default = (0, util_1.createRule)({
201
209
  return null;
202
210
  }
203
211
  }
204
- function reportUselessDefault(node, type, messageId) {
212
+ function reportUselessDefaultAssignment(node, type) {
213
+ context.report({
214
+ node: node.right,
215
+ messageId: 'uselessDefaultAssignment',
216
+ data: { type },
217
+ fix: fixer => removeDefault(fixer, node),
218
+ });
219
+ }
220
+ function reportUselessUndefined(node, type) {
205
221
  context.report({
206
222
  node: node.right,
207
- messageId,
223
+ messageId: 'uselessUndefined',
208
224
  data: { type },
209
- fix(fixer) {
210
- // Remove from before the = to the end of the default value
211
- // Find the start position (including whitespace before =)
212
- const start = node.left.range[1];
213
- const end = node.range[1];
214
- return fixer.removeRange([start, end]);
225
+ fix: fixer => removeDefault(fixer, node),
226
+ });
227
+ }
228
+ function reportPreferOptionalSyntax(node) {
229
+ context.report({
230
+ node: node.right,
231
+ messageId: 'preferOptionalSyntax',
232
+ *fix(fixer) {
233
+ yield removeDefault(fixer, node);
234
+ const { left } = node;
235
+ if (left.type === utils_1.AST_NODE_TYPES.Identifier) {
236
+ yield fixer.insertTextAfterRange([left.range[0], left.range[0] + left.name.length], '?');
237
+ }
215
238
  },
216
239
  });
217
240
  }
241
+ function removeDefault(fixer, node) {
242
+ const start = node.left.range[1];
243
+ const end = node.range[1];
244
+ return fixer.removeRange([start, end]);
245
+ }
218
246
  return {
219
247
  AssignmentPattern: checkAssignmentPattern,
220
248
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.50.2-alpha.14",
3
+ "version": "8.50.2-alpha.16",
4
4
  "description": "TypeScript plugin for ESLint",
5
5
  "files": [
6
6
  "dist",
@@ -59,10 +59,10 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@eslint-community/regexpp": "^4.10.0",
62
- "@typescript-eslint/scope-manager": "8.50.2-alpha.14",
63
- "@typescript-eslint/type-utils": "8.50.2-alpha.14",
64
- "@typescript-eslint/utils": "8.50.2-alpha.14",
65
- "@typescript-eslint/visitor-keys": "8.50.2-alpha.14",
62
+ "@typescript-eslint/scope-manager": "8.50.2-alpha.16",
63
+ "@typescript-eslint/type-utils": "8.50.2-alpha.16",
64
+ "@typescript-eslint/utils": "8.50.2-alpha.16",
65
+ "@typescript-eslint/visitor-keys": "8.50.2-alpha.16",
66
66
  "ignore": "^7.0.0",
67
67
  "natural-compare": "^1.4.0",
68
68
  "ts-api-utils": "^2.2.0"
@@ -70,8 +70,8 @@
70
70
  "devDependencies": {
71
71
  "@types/mdast": "^4.0.3",
72
72
  "@types/natural-compare": "*",
73
- "@typescript-eslint/rule-schema-to-typescript-types": "8.50.2-alpha.14",
74
- "@typescript-eslint/rule-tester": "8.50.2-alpha.14",
73
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.50.2-alpha.16",
74
+ "@typescript-eslint/rule-tester": "8.50.2-alpha.16",
75
75
  "@vitest/coverage-v8": "^3.1.3",
76
76
  "ajv": "^6.12.6",
77
77
  "eslint": "*",
@@ -90,7 +90,7 @@
90
90
  "vitest": "^3.1.3"
91
91
  },
92
92
  "peerDependencies": {
93
- "@typescript-eslint/parser": "^8.50.2-alpha.14",
93
+ "@typescript-eslint/parser": "^8.50.2-alpha.16",
94
94
  "eslint": "^8.57.0 || ^9.0.0",
95
95
  "typescript": ">=4.8.4 <6.0.0"
96
96
  },