@typescript-eslint/eslint-plugin 8.50.1-alpha.0 → 8.50.1-alpha.2

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.
@@ -83,6 +83,7 @@ exports.default = (0, util_1.createRule)({
83
83
  if (methodNode.kind !== 'method') {
84
84
  return;
85
85
  }
86
+ const skipFix = returnTypeReferencesThisType(methodNode.returnType);
86
87
  const parent = methodNode.parent;
87
88
  const members = parent.type === utils_1.AST_NODE_TYPES.TSInterfaceBody
88
89
  ? parent.body
@@ -102,32 +103,34 @@ exports.default = (0, util_1.createRule)({
102
103
  context.report({
103
104
  node: methodNode,
104
105
  messageId: 'errorMethod',
105
- *fix(fixer) {
106
- const methodNodes = [
107
- methodNode,
108
- ...duplicatedKeyMethodNodes,
109
- ].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1));
110
- const typeString = methodNodes
111
- .map(node => {
112
- const params = getMethodParams(node);
113
- const returnType = getMethodReturnType(node);
114
- return `(${params} => ${returnType})`;
115
- })
116
- .join(' & ');
117
- const key = getMethodKey(methodNode);
118
- const delimiter = getDelimiter(methodNode);
119
- yield fixer.replaceText(methodNode, `${key}: ${typeString}${delimiter}`);
120
- for (const node of duplicatedKeyMethodNodes) {
121
- const lastToken = context.sourceCode.getLastToken(node);
122
- if (lastToken) {
123
- const nextToken = context.sourceCode.getTokenAfter(lastToken);
124
- if (nextToken) {
125
- yield fixer.remove(node);
126
- yield fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], '');
106
+ fix: skipFix
107
+ ? undefined
108
+ : function* fix(fixer) {
109
+ const methodNodes = [
110
+ methodNode,
111
+ ...duplicatedKeyMethodNodes,
112
+ ].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1));
113
+ const typeString = methodNodes
114
+ .map(node => {
115
+ const params = getMethodParams(node);
116
+ const returnType = getMethodReturnType(node);
117
+ return `(${params} => ${returnType})`;
118
+ })
119
+ .join(' & ');
120
+ const key = getMethodKey(methodNode);
121
+ const delimiter = getDelimiter(methodNode);
122
+ yield fixer.replaceText(methodNode, `${key}: ${typeString}${delimiter}`);
123
+ for (const node of duplicatedKeyMethodNodes) {
124
+ const lastToken = context.sourceCode.getLastToken(node);
125
+ if (lastToken) {
126
+ const nextToken = context.sourceCode.getTokenAfter(lastToken);
127
+ if (nextToken) {
128
+ yield fixer.remove(node);
129
+ yield fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], '');
130
+ }
127
131
  }
128
132
  }
129
- }
130
- },
133
+ },
131
134
  });
132
135
  }
133
136
  return;
@@ -142,13 +145,15 @@ exports.default = (0, util_1.createRule)({
142
145
  context.report({
143
146
  node: methodNode,
144
147
  messageId: 'errorMethod',
145
- fix: fixer => {
146
- const key = getMethodKey(methodNode);
147
- const params = getMethodParams(methodNode);
148
- const returnType = getMethodReturnType(methodNode);
149
- const delimiter = getDelimiter(methodNode);
150
- return fixer.replaceText(methodNode, `${key}: ${params} => ${returnType}${delimiter}`);
151
- },
148
+ fix: skipFix
149
+ ? undefined
150
+ : fixer => {
151
+ const key = getMethodKey(methodNode);
152
+ const params = getMethodParams(methodNode);
153
+ const returnType = getMethodReturnType(methodNode);
154
+ const delimiter = getDelimiter(methodNode);
155
+ return fixer.replaceText(methodNode, `${key}: ${params} => ${returnType}${delimiter}`);
156
+ },
152
157
  });
153
158
  }
154
159
  },
@@ -175,3 +180,7 @@ exports.default = (0, util_1.createRule)({
175
180
  };
176
181
  },
177
182
  });
183
+ function returnTypeReferencesThisType(node) {
184
+ return (node &&
185
+ (0, util_1.forEachChildESTree)(node.typeAnnotation, child => child.type === utils_1.AST_NODE_TYPES.TSThisType));
186
+ }
@@ -187,6 +187,30 @@ exports.default = (0, util_1.createRule)({
187
187
  function isTypeLiteral(type) {
188
188
  return type.isLiteral() || tsutils.isBooleanLiteralType(type);
189
189
  }
190
+ function isIIFE(expression) {
191
+ return (expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
192
+ (expression.callee.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
193
+ expression.callee.type === utils_1.AST_NODE_TYPES.FunctionExpression));
194
+ }
195
+ function getUncastType(node) {
196
+ // Special handling for IIFE: extract the function's return type
197
+ if (isIIFE(node.expression)) {
198
+ const callee = node.expression.callee;
199
+ const functionType = services.getTypeAtLocation(callee);
200
+ const signatures = functionType.getCallSignatures();
201
+ if (signatures.length > 0) {
202
+ const returnType = checker.getReturnTypeOfSignature(signatures[0]);
203
+ // If the function has no explicit return type annotation and returns undefined,
204
+ // treat it as void (TypeScript infers () => {} as () => undefined, but it should be void)
205
+ if (callee.returnType == null &&
206
+ (0, util_1.isTypeFlagSet)(returnType, ts.TypeFlags.Undefined)) {
207
+ return checker.getVoidType();
208
+ }
209
+ return returnType;
210
+ }
211
+ }
212
+ return services.getTypeAtLocation(node.expression);
213
+ }
190
214
  return {
191
215
  'TSAsExpression, TSTypeAssertion'(node) {
192
216
  if (options.typesToIgnore?.includes(context.sourceCode.getText(node.typeAnnotation))) {
@@ -200,7 +224,7 @@ exports.default = (0, util_1.createRule)({
200
224
  typeAnnotationIsConstAssertion) {
201
225
  return;
202
226
  }
203
- const uncastType = services.getTypeAtLocation(node.expression);
227
+ const uncastType = getUncastType(node);
204
228
  const typeIsUnchanged = isTypeUnchanged(uncastType, castType);
205
229
  const wouldSameTypeBeInferred = castTypeIsLiteral
206
230
  ? isImplicitlyNarrowedLiteralDeclaration(node)
@@ -10,3 +10,8 @@ export * from '@typescript-eslint/utils/ast-utils';
10
10
  */
11
11
  export declare function getNameLocationInGlobalDirectiveComment(sourceCode: TSESLint.SourceCode, comment: TSESTree.Comment, name: string): TSESTree.SourceLocation;
12
12
  export declare function forEachReturnStatement<T>(body: ts.Block, visitor: (stmt: ts.ReturnStatement) => T): T | undefined;
13
+ /**
14
+ * Rough equivalent to ts.forEachChild for ESTree nodes.
15
+ * It returns the first truthy value returned by the callback, if any.
16
+ */
17
+ export declare function forEachChildESTree<Result>(node: TSESTree.Node, callback: (child: TSESTree.Node) => false | Result | null | undefined): Result | undefined;
@@ -38,6 +38,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.getNameLocationInGlobalDirectiveComment = getNameLocationInGlobalDirectiveComment;
40
40
  exports.forEachReturnStatement = forEachReturnStatement;
41
+ exports.forEachChildESTree = forEachChildESTree;
42
+ const visitor_keys_1 = require("@typescript-eslint/visitor-keys");
41
43
  const ts = __importStar(require("typescript"));
42
44
  const escapeRegExp_1 = require("./escapeRegExp");
43
45
  // deeply re-export, for convenience
@@ -95,3 +97,47 @@ function forEachReturnStatement(body, visitor) {
95
97
  return undefined;
96
98
  }
97
99
  }
100
+ function isESTreeNodeLike(node) {
101
+ return (typeof node === 'object' &&
102
+ node != null &&
103
+ 'type' in node &&
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
105
+ typeof node.type === 'string');
106
+ }
107
+ /**
108
+ * Rough equivalent to ts.forEachChild for ESTree nodes.
109
+ * It returns the first truthy value returned by the callback, if any.
110
+ */
111
+ function forEachChildESTree(node, callback) {
112
+ function visit(currentNode) {
113
+ const result = callback(currentNode);
114
+ if (result) {
115
+ return result;
116
+ }
117
+ const currentKeys = visitor_keys_1.visitorKeys[currentNode.type];
118
+ if (!currentKeys) {
119
+ return undefined;
120
+ }
121
+ for (const key of currentKeys) {
122
+ const currentProperty = currentNode[key];
123
+ if (Array.isArray(currentProperty)) {
124
+ for (const child of currentProperty) {
125
+ if (isESTreeNodeLike(child)) {
126
+ const result = visit(child);
127
+ if (result) {
128
+ return result;
129
+ }
130
+ }
131
+ }
132
+ }
133
+ else if (isESTreeNodeLike(currentProperty)) {
134
+ const result = visit(currentProperty);
135
+ if (result) {
136
+ return result;
137
+ }
138
+ }
139
+ }
140
+ return undefined;
141
+ }
142
+ return visit(node);
143
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.50.1-alpha.0",
3
+ "version": "8.50.1-alpha.2",
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.1-alpha.0",
63
- "@typescript-eslint/type-utils": "8.50.1-alpha.0",
64
- "@typescript-eslint/utils": "8.50.1-alpha.0",
65
- "@typescript-eslint/visitor-keys": "8.50.1-alpha.0",
62
+ "@typescript-eslint/scope-manager": "8.50.1-alpha.2",
63
+ "@typescript-eslint/type-utils": "8.50.1-alpha.2",
64
+ "@typescript-eslint/utils": "8.50.1-alpha.2",
65
+ "@typescript-eslint/visitor-keys": "8.50.1-alpha.2",
66
66
  "ignore": "^7.0.0",
67
67
  "natural-compare": "^1.4.0",
68
68
  "ts-api-utils": "^2.1.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.1-alpha.0",
74
- "@typescript-eslint/rule-tester": "8.50.1-alpha.0",
73
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.50.1-alpha.2",
74
+ "@typescript-eslint/rule-tester": "8.50.1-alpha.2",
75
75
  "@vitest/coverage-v8": "^3.1.3",
76
76
  "ajv": "^6.12.6",
77
77
  "cross-fetch": "*",
@@ -91,7 +91,7 @@
91
91
  "vitest": "^3.1.3"
92
92
  },
93
93
  "peerDependencies": {
94
- "@typescript-eslint/parser": "^8.50.1-alpha.0",
94
+ "@typescript-eslint/parser": "^8.50.1-alpha.2",
95
95
  "eslint": "^8.57.0 || ^9.0.0",
96
96
  "typescript": ">=4.8.4 <6.0.0"
97
97
  },