fix(eslint-plugin): [no-shadow] correct rule to match ESLint v10 handling#12182
Conversation
|
Thanks for the PR, @nevette-bailey! typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community. The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately. Thanks again! 🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint. |
✅ Deploy Preview for typescript-eslint ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
View your CI Pipeline Execution ↗ for commit 3a69108
☁️ Nx Cloud last updated this comment at |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #12182 +/- ##
==========================================
+ Coverage 86.52% 86.75% +0.22%
==========================================
Files 501 512 +11
Lines 16275 16306 +31
Branches 5069 5079 +10
==========================================
+ Hits 14082 14146 +64
+ Misses 1506 1473 -33
Partials 687 687
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
JoshuaKGoldberg
left a comment
There was a problem hiding this comment.
Super, thanks for this! 🙌
f525814
into
typescript-eslint:main
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.60.0 | 8.60.1 | | npm | @typescript-eslint/parser | 8.60.0 | 8.60.1 | ## [v8.60.1](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8601-2026-06-01) ##### 🩹 Fixes - **eslint-plugin:** \[no-shadow] correct rule to match ESLint v10 handling ([#12182](typescript-eslint/typescript-eslint#12182)) - **eslint-plugin:** respect ECMAScript line terminators in ts-comment rules ([#12352](typescript-eslint/typescript-eslint#12352)) ##### ❤️ Thank You - lumir - Nevette Bailey [@nevette-bailey](https://github.com/nevette-bailey) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.60.1) for more information. You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
|
@JoshuaKGoldberg @nevette-bailey Hi, assuming we liked the previous behaviour ( |
|
https://typescript-eslint.io/contributing/issues#commenting Do not comment on closed PRs. |

PR Checklist
Overview
The
no-shadowrule reports when a variable in an inner scope "shadows" (reuses the same name and hides) a variable in an outer scope. There is a deliberate exception when named function/class expressions are assigned directly to a variable of the same name that is allowed, common, and a harmless self-reference:In this case, the function's inner name only exists inside of the function itself, so reporting it as a shadow would be noisy and unhelpful.
The Bug
The
isOnInitializerhelper previously used a range-containment check to decide if this exception should be applied, by asking "is the inner variable located somewhere inside the declaration of the outer variable?" This definition was too loose because it suppressed shadow reports for named expressions anywhere inside an initializer, not just direct initializers, such as this case that should be reported because the inner definition is a genuinely separate binding that shadows the outer one:ESLint v10 started to correctly report these cases.
The Fix
Instead of asking "is the inner name somewhere inside the initializer?", this PR rewrites to ask "is the inner expression literally the initializer?" It does this by:
isOnInitializerto walk from the outer variable to its actual initializer nodeThe
unwrapExpressionhelper handles these still-valid cases where the function expression can transparently becomeaat runtime:The previous code also had a check for class expressions that verified the node type but not the definition type, even though a definition bundles both. The fix adds a missing
DefinitionType.ClassNamecheck for class expressions so that bothinnerDef.node.typeandinnerDef.typeare now checked.Fixes #12070.
💖