@typescript-eslint/eslint-plugin 8.71.1-alpha.0 → 8.71.1-alpha.10

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.
@@ -337,8 +337,9 @@ exports.default = (0, util_1.createRule)({
337
337
  }
338
338
  }
339
339
  function checkArguments(node) {
340
- if (node.type === utils_1.AST_NODE_TYPES.CallExpression &&
341
- isPromiseFinallyMethod(node)) {
340
+ if (node.arguments.length === 0 ||
341
+ (node.type === utils_1.AST_NODE_TYPES.CallExpression &&
342
+ isPromiseFinallyMethod(node))) {
342
343
  return;
343
344
  }
344
345
  const tsNode = services.esTreeNodeToTSNodeMap.get(node);
@@ -147,7 +147,7 @@ exports.default = (0, util_1.createRule)({
147
147
  }
148
148
  }
149
149
  function isUnsafeAssignment(senderNode, receiverType, senderType = services.getTypeAtLocation(senderNode)) {
150
- return (hasDeepEnumAssignmentMismatch(checker, senderType, receiverType) &&
150
+ return (hasEnumAssignmentMismatch(checker, senderType, receiverType) &&
151
151
  !isSafeEnumBitwiseExpression(senderNode, receiverType));
152
152
  }
153
153
  function checkAssignment(receiverType, senderNode, reportingNode, messageId = 'unsafeEnumAssignment', senderType) {
@@ -181,7 +181,7 @@ exports.default = (0, util_1.createRule)({
181
181
  .flatMap(elementType => {
182
182
  const parameterType = signature.getNextParameterType();
183
183
  return parameterType != null &&
184
- hasDeepEnumAssignmentMismatch(checker, elementType, parameterType)
184
+ hasEnumAssignmentMismatch(checker, elementType, parameterType)
185
185
  ? [parameterType]
186
186
  : [];
187
187
  });
@@ -311,7 +311,8 @@ exports.default = (0, util_1.createRule)({
311
311
  // declare const foo: { [key in Fruit]: string };
312
312
  // foo[0];
313
313
  const senderType = services.getTypeAtLocation(node.property);
314
- if (receiverTypes.every(receiverType => hasDeepEnumAssignmentMismatch(checker, senderType, receiverType) || !checker.isTypeAssignableTo(senderType, receiverType))) {
314
+ if (receiverTypes.every(receiverType => hasEnumAssignmentMismatch(checker, senderType, receiverType) ||
315
+ !checker.isTypeAssignableTo(senderType, receiverType))) {
315
316
  report(node.property, 'unsafeEnumAccess', receiverTypes);
316
317
  }
317
318
  },
@@ -355,9 +356,46 @@ function getConstraintType(checker, type) {
355
356
  function getTypeArguments(checker, type) {
356
357
  return tsutils.isTypeReference(type) ? checker.getTypeArguments(type) : [];
357
358
  }
358
- function hasDeepEnumAssignmentMismatch(checker, senderType, receiverType, visited = new WeakMap()) {
359
+ const genericTypes = new WeakMap();
360
+ function isGenericType(checker, type) {
361
+ let generic = genericTypes.get(type);
362
+ if (generic == null) {
363
+ genericTypes.set(type, false);
364
+ generic =
365
+ tsutils.isTypeFlagSet(type, ts.TypeFlags.Instantiable) ||
366
+ [
367
+ ...(tsutils.isUnionOrIntersectionType(type) ? type.types : []),
368
+ ...(type.aliasTypeArguments ?? []),
369
+ ...getTypeArguments(checker, type),
370
+ ].some(part => isGenericType(checker, part));
371
+ genericTypes.set(type, generic);
372
+ }
373
+ return generic;
374
+ }
375
+ const maximumDepth = 5;
376
+ const topLevelMismatches = new WeakMap();
377
+ function hasEnumAssignmentMismatch(checker, senderType, receiverType) {
378
+ let receiverMismatches = topLevelMismatches.get(senderType);
379
+ if (receiverMismatches == null) {
380
+ receiverMismatches = new WeakMap();
381
+ topLevelMismatches.set(senderType, receiverMismatches);
382
+ }
383
+ let mismatch = receiverMismatches.get(receiverType);
384
+ if (mismatch == null) {
385
+ mismatch = hasDeepEnumAssignmentMismatch(checker, senderType, receiverType);
386
+ receiverMismatches.set(receiverType, mismatch);
387
+ }
388
+ return mismatch;
389
+ }
390
+ function hasDeepEnumAssignmentMismatch(checker, senderType, receiverType, visited = new WeakMap(), depth = 0, withinGenericMembers = false) {
391
+ if (depth > maximumDepth) {
392
+ return false;
393
+ }
359
394
  const constrainedSenderType = getConstraintType(checker, senderType);
360
395
  const constrainedReceiverType = getConstraintType(checker, receiverType);
396
+ if (constrainedSenderType === constrainedReceiverType) {
397
+ return false;
398
+ }
361
399
  // Recursive types would otherwise be visited endlessly.
362
400
  let visitedReceiverTypes = visited.get(constrainedSenderType);
363
401
  if (visitedReceiverTypes == null) {
@@ -375,22 +413,28 @@ function hasDeepEnumAssignmentMismatch(checker, senderType, receiverType, visite
375
413
  const senderTypeArguments = getTypeArguments(checker, constrainedSenderType);
376
414
  const receiverTypeArguments = getTypeArguments(checker, constrainedReceiverType);
377
415
  if (senderTypeArguments.length === receiverTypeArguments.length &&
378
- senderTypeArguments.some((senderTypeArgument, index) => hasDeepEnumAssignmentMismatch(checker, senderTypeArgument, receiverTypeArguments[index], visited))) {
416
+ senderTypeArguments.some((senderTypeArgument, index) => hasDeepEnumAssignmentMismatch(checker, senderTypeArgument, receiverTypeArguments[index], visited, depth + 1, withinGenericMembers))) {
379
417
  return true;
380
418
  }
419
+ // Members of generic types can instantiate ever-larger generic types.
420
+ const generic = isGenericType(checker, constrainedSenderType) ||
421
+ isGenericType(checker, constrainedReceiverType);
422
+ if (generic && withinGenericMembers) {
423
+ return false;
424
+ }
381
425
  // [number, Fruit] -> Fruit[]
382
426
  const senderElementType = constrainedSenderType.getNumberIndexType();
383
427
  const receiverElementType = constrainedReceiverType.getNumberIndexType();
384
428
  if (senderElementType &&
385
429
  receiverElementType &&
386
- hasDeepEnumAssignmentMismatch(checker, senderElementType, receiverElementType, visited)) {
430
+ hasDeepEnumAssignmentMismatch(checker, senderElementType, receiverElementType, visited, depth + 1, generic || withinGenericMembers)) {
387
431
  return true;
388
432
  }
389
433
  // { fruit: number } -> { fruit: Fruit }
390
434
  return constrainedReceiverType.getProperties().some(receiverProperty => {
391
435
  const senderProperty = constrainedSenderType.getProperty(receiverProperty.name);
392
436
  return (senderProperty != null &&
393
- hasDeepEnumAssignmentMismatch(checker, checker.getTypeOfSymbol(senderProperty), checker.getTypeOfSymbol(receiverProperty), visited));
437
+ hasDeepEnumAssignmentMismatch(checker, checker.getTypeOfSymbol(senderProperty), checker.getTypeOfSymbol(receiverProperty), visited, depth + 1, generic || withinGenericMembers));
394
438
  });
395
439
  }
396
440
  function getMappedKeyConstraintTypes(checker, declaration) {
@@ -3,8 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const scope_manager_1 = require("@typescript-eslint/scope-manager");
4
4
  const utils_1 = require("@typescript-eslint/utils");
5
5
  const util_1 = require("../util");
6
- const referenceContainsTypePredicate_1 = require("../util/referenceContainsTypePredicate");
7
- const referenceContainsTypeQuery_1 = require("../util/referenceContainsTypeQuery");
6
+ const isTypeOnlyReference_1 = require("../util/isTypeOnlyReference");
8
7
  // this is a superset of DefinitionType which defines sub-types for better granularity
9
8
  var VariableType;
10
9
  (function (VariableType) {
@@ -821,8 +820,7 @@ exports.default = (0, util_1.createRule)({
821
820
  for (const unusedVar of unusedVars) {
822
821
  // Report the first declaration.
823
822
  if (unusedVar.defs.length > 0) {
824
- const usedOnlyAsType = unusedVar.references.some(ref => (0, referenceContainsTypeQuery_1.referenceContainsTypeQuery)(ref.identifier) ||
825
- (0, referenceContainsTypePredicate_1.referenceContainsTypePredicate)(ref.identifier));
823
+ const usedOnlyAsType = unusedVar.references.some(ref => (0, isTypeOnlyReference_1.isTypeOnlyReference)(unusedVar, ref));
826
824
  const messageId = usedOnlyAsType ? 'usedOnlyAsType' : 'unusedVar';
827
825
  const isImportUsedOnlyAsType = usedOnlyAsType &&
828
826
  unusedVar.defs.some(def => def.type === scope_manager_1.DefinitionType.ImportBinding);
@@ -40,7 +40,10 @@ exports.default = (0, util_1.createRule)({
40
40
  const type = (0, util_1.getConstrainedTypeAtLocation)(services, node);
41
41
  if (checker.isArrayType(type) || checker.isTupleType(type)) {
42
42
  const typeArgs = checker.getTypeArguments(type);
43
- return typeArgs.every(arg => (0, util_1.getTypeName)(checker, arg) === 'string');
43
+ return typeArgs.every(arg => {
44
+ const typeName = (0, util_1.getTypeName)(checker, checker.getBaseConstraintOfType(arg) ?? arg);
45
+ return typeName === 'string';
46
+ });
44
47
  }
45
48
  return false;
46
49
  }
@@ -4,8 +4,7 @@ exports.collectVariables = collectVariables;
4
4
  const scope_manager_1 = require("@typescript-eslint/scope-manager");
5
5
  const utils_1 = require("@typescript-eslint/utils");
6
6
  const isTypeImport_1 = require("./isTypeImport");
7
- const referenceContainsTypePredicate_1 = require("./referenceContainsTypePredicate");
8
- const referenceContainsTypeQuery_1 = require("./referenceContainsTypeQuery");
7
+ const isTypeOnlyReference_1 = require("./isTypeOnlyReference");
9
8
  /**
10
9
  * This class leverages an AST visitor to mark variables as used via the
11
10
  * `eslintUsed` property.
@@ -289,6 +288,11 @@ const MERGEABLE_TYPES = new Set([
289
288
  utils_1.AST_NODE_TYPES.TSModuleDeclaration,
290
289
  utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration,
291
290
  ]);
291
+ function isMergedTypeDeclaration(variable, node) {
292
+ return ((node.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration ||
293
+ node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) &&
294
+ (0, isTypeOnlyReference_1.isMergedTypeValueVariable)(variable));
295
+ }
292
296
  /**
293
297
  * Determine if the variable is directly exported
294
298
  * @param variable the variable to check
@@ -305,7 +309,7 @@ function isMergeableExported(variable) {
305
309
  if ((MERGEABLE_TYPES.has(def.node.type) &&
306
310
  def.node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) ||
307
311
  def.node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) {
308
- return true;
312
+ return !isMergedTypeDeclaration(variable, def.node);
309
313
  }
310
314
  }
311
315
  return false;
@@ -324,7 +328,8 @@ function isExported(variable) {
324
328
  else if (definition.type === utils_1.TSESLint.Scope.DefinitionType.Parameter) {
325
329
  return false;
326
330
  }
327
- return node.parent.type.startsWith('Export');
331
+ return (!isMergedTypeDeclaration(variable, node) &&
332
+ node.parent.type.startsWith('Export'));
328
333
  });
329
334
  }
330
335
  const LOGICAL_ASSIGNMENT_OPERATORS = new Set(['??=', '&&=', '||=']);
@@ -579,9 +584,7 @@ function isUsedVariable(variable) {
579
584
  rhsNode = getRhsNode(ref, rhsNode);
580
585
  return (ref.isRead() &&
581
586
  !forItself &&
582
- !(!isImportedAsType &&
583
- ((0, referenceContainsTypeQuery_1.referenceContainsTypeQuery)(ref.identifier) ||
584
- (0, referenceContainsTypePredicate_1.referenceContainsTypePredicate)(ref.identifier))) &&
587
+ !(!isImportedAsType && (0, isTypeOnlyReference_1.isTypeOnlyReference)(variable, ref)) &&
585
588
  !(isFunctionDefinition && isSelfReference(ref, functionNodes)) &&
586
589
  !(isTypeDecl && isInsideOneOf(ref, typeDeclNodes)) &&
587
590
  !(isModuleDecl && isSelfReference(ref, moduleDeclNodes)) &&
@@ -0,0 +1,4 @@
1
+ import type { ScopeVariable } from '@typescript-eslint/scope-manager';
2
+ import type { TSESLint } from '@typescript-eslint/utils';
3
+ export declare function isMergedTypeValueVariable(variable: ScopeVariable): boolean;
4
+ export declare function isTypeOnlyReference(variable: ScopeVariable, ref: TSESLint.Scope.Reference): boolean;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isMergedTypeValueVariable = isMergedTypeValueVariable;
4
+ exports.isTypeOnlyReference = isTypeOnlyReference;
5
+ const scope_manager_1 = require("@typescript-eslint/scope-manager");
6
+ const referenceContainsTypePredicate_1 = require("./referenceContainsTypePredicate");
7
+ const referenceContainsTypeQuery_1 = require("./referenceContainsTypeQuery");
8
+ function isMergedTypeValueVariable(variable) {
9
+ return ('isTypeVariable' in variable &&
10
+ 'isValueVariable' in variable &&
11
+ variable.isTypeVariable &&
12
+ variable.isValueVariable);
13
+ }
14
+ function isTypeOnlyReference(variable, ref) {
15
+ if ((0, referenceContainsTypeQuery_1.referenceContainsTypeQuery)(ref.identifier) ||
16
+ (0, referenceContainsTypePredicate_1.referenceContainsTypePredicate)(ref.identifier)) {
17
+ return true;
18
+ }
19
+ return (variable.defs.some(def => def.type === scope_manager_1.DefinitionType.Variable) &&
20
+ !ref.isValueReference);
21
+ }
22
+ //# sourceMappingURL=isTypeOnlyReference.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.71.1-alpha.0",
3
+ "version": "8.71.1-alpha.10",
4
4
  "description": "TypeScript plugin for ESLint",
5
5
  "files": [
6
6
  "dist",
@@ -47,10 +47,10 @@
47
47
  ],
48
48
  "dependencies": {
49
49
  "@eslint-community/regexpp": "^4.12.2",
50
- "@typescript-eslint/scope-manager": "8.71.1-alpha.0",
51
- "@typescript-eslint/type-utils": "8.71.1-alpha.0",
52
- "@typescript-eslint/utils": "8.71.1-alpha.0",
53
- "@typescript-eslint/visitor-keys": "8.71.1-alpha.0",
50
+ "@typescript-eslint/scope-manager": "8.71.1-alpha.10",
51
+ "@typescript-eslint/type-utils": "8.71.1-alpha.10",
52
+ "@typescript-eslint/utils": "8.71.1-alpha.10",
53
+ "@typescript-eslint/visitor-keys": "8.71.1-alpha.10",
54
54
  "ignore": "^7.0.5",
55
55
  "natural-compare": "^1.4.0",
56
56
  "ts-api-utils": "^2.5.0"
@@ -60,8 +60,8 @@
60
60
  "@types/mdast": "^4.0.4",
61
61
  "@types/natural-compare": "^1.4.3",
62
62
  "@types/react": "^18.3.21",
63
- "@typescript-eslint/rule-schema-to-typescript-types": "8.71.1-alpha.0",
64
- "@typescript-eslint/rule-tester": "8.71.1-alpha.0",
63
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.71.1-alpha.10",
64
+ "@typescript-eslint/rule-tester": "8.71.1-alpha.10",
65
65
  "@typescript/native": "npm:typescript@^7.0.2",
66
66
  "@vitest/coverage-v8": "^4.0.18",
67
67
  "ajv": "^6.12.6",
@@ -81,7 +81,7 @@
81
81
  "vitest": "^4.0.18"
82
82
  },
83
83
  "peerDependencies": {
84
- "@typescript-eslint/parser": "^8.71.1-alpha.0",
84
+ "@typescript-eslint/parser": "^8.71.1-alpha.10",
85
85
  "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
86
86
  "typescript": ">=4.8.4 <6.1.0"
87
87
  },