@typescript-eslint/eslint-plugin 8.53.2-alpha.4 → 8.53.2-alpha.6

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.
@@ -281,8 +281,17 @@ exports.default = (0, util_1.createRule)({
281
281
  return;
282
282
  }
283
283
  const originalNode = services.esTreeNodeToTSNodeMap.get(node);
284
- const type = (0, util_1.getConstrainedTypeAtLocation)(services, node.expression);
285
- if (!(0, util_1.isNullableType)(type)) {
284
+ const constrainedType = (0, util_1.getConstrainedTypeAtLocation)(services, node.expression);
285
+ const actualType = services.getTypeAtLocation(node.expression);
286
+ // Check both the constrained type and the actual type.
287
+ // If either is nullable, we should not report the assertion as unnecessary.
288
+ // This handles cases like generic constraints with `any` where the
289
+ // constrained type is `any` (nullable) but the actual type might be
290
+ // a type parameter that TypeScript treats nominally.
291
+ // See: https://github.com/typescript-eslint/typescript-eslint/issues/11559
292
+ const constrainedTypeIsNullable = (0, util_1.isNullableType)(constrainedType);
293
+ const actualTypeIsNullable = (0, util_1.isNullableType)(actualType);
294
+ if (!constrainedTypeIsNullable && !actualTypeIsNullable) {
286
295
  if (node.expression.type === utils_1.AST_NODE_TYPES.Identifier &&
287
296
  isPossiblyUsedBeforeAssigned(node.expression)) {
288
297
  return;
@@ -296,17 +305,25 @@ exports.default = (0, util_1.createRule)({
296
305
  else {
297
306
  // we know it's a nullable type
298
307
  // so figure out if the variable is used in a place that accepts nullable types
308
+ // If the constrained type differs from the actual type (e.g., when dealing
309
+ // with unresolved generic type parameters), we should not report the assertion
310
+ // as contextually unnecessary. TypeScript may still require the assertion
311
+ // even if the constraint is nullable (like `any`).
312
+ // See: https://github.com/typescript-eslint/typescript-eslint/issues/11559
313
+ if (constrainedType !== actualType) {
314
+ return;
315
+ }
299
316
  const contextualType = (0, util_1.getContextualType)(checker, originalNode);
300
317
  if (contextualType) {
301
- if ((0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Unknown) &&
318
+ if ((0, util_1.isTypeFlagSet)(constrainedType, ts.TypeFlags.Unknown) &&
302
319
  !(0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Unknown)) {
303
320
  return;
304
321
  }
305
322
  // in strict mode you can't assign null to undefined, so we have to make sure that
306
323
  // the two types share a nullable type
307
- const typeIncludesUndefined = (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Undefined);
308
- const typeIncludesNull = (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Null);
309
- const typeIncludesVoid = (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Void);
324
+ const typeIncludesUndefined = (0, util_1.isTypeFlagSet)(constrainedType, ts.TypeFlags.Undefined);
325
+ const typeIncludesNull = (0, util_1.isTypeFlagSet)(constrainedType, ts.TypeFlags.Null);
326
+ const typeIncludesVoid = (0, util_1.isTypeFlagSet)(constrainedType, ts.TypeFlags.Void);
310
327
  const contextualTypeIncludesUndefined = (0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Undefined);
311
328
  const contextualTypeIncludesNull = (0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Null);
312
329
  const contextualTypeIncludesVoid = (0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Void);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.53.2-alpha.4",
3
+ "version": "8.53.2-alpha.6",
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.12.2",
62
- "@typescript-eslint/scope-manager": "8.53.2-alpha.4",
63
- "@typescript-eslint/type-utils": "8.53.2-alpha.4",
64
- "@typescript-eslint/utils": "8.53.2-alpha.4",
65
- "@typescript-eslint/visitor-keys": "8.53.2-alpha.4",
62
+ "@typescript-eslint/scope-manager": "8.53.2-alpha.6",
63
+ "@typescript-eslint/type-utils": "8.53.2-alpha.6",
64
+ "@typescript-eslint/utils": "8.53.2-alpha.6",
65
+ "@typescript-eslint/visitor-keys": "8.53.2-alpha.6",
66
66
  "ignore": "^7.0.5",
67
67
  "natural-compare": "^1.4.0",
68
68
  "ts-api-utils": "^2.4.0"
@@ -70,8 +70,8 @@
70
70
  "devDependencies": {
71
71
  "@types/mdast": "^4.0.4",
72
72
  "@types/natural-compare": "*",
73
- "@typescript-eslint/rule-schema-to-typescript-types": "8.53.2-alpha.4",
74
- "@typescript-eslint/rule-tester": "8.53.2-alpha.4",
73
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.53.2-alpha.6",
74
+ "@typescript-eslint/rule-tester": "8.53.2-alpha.6",
75
75
  "@vitest/coverage-v8": "^3.2.4",
76
76
  "ajv": "^6.12.6",
77
77
  "eslint": "*",
@@ -81,7 +81,7 @@
81
81
  "mdast-util-from-markdown": "^2.0.2",
82
82
  "mdast-util-mdx": "^3.0.0",
83
83
  "micromark-extension-mdxjs": "^3.0.0",
84
- "prettier": "3.7.4",
84
+ "prettier": "3.8.0",
85
85
  "rimraf": "*",
86
86
  "title-case": "^4.3.2",
87
87
  "tsx": "*",
@@ -90,7 +90,7 @@
90
90
  "vitest": "^3.2.4"
91
91
  },
92
92
  "peerDependencies": {
93
- "@typescript-eslint/parser": "^8.53.2-alpha.4",
93
+ "@typescript-eslint/parser": "^8.53.2-alpha.6",
94
94
  "eslint": "^8.57.0 || ^9.0.0",
95
95
  "typescript": ">=4.8.4 <6.0.0"
96
96
  },