fix(eslint-plugin): [unified-signatures] compare type parameters by constraint instead of name - #12741
Conversation
…raints by type, not node kind
|
Thanks for the PR, @Arlikhozhaev! 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 8c1a91c
☁️ 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 #12741 +/- ##
==========================================
- Coverage 94.93% 94.93% -0.01%
==========================================
Files 226 226
Lines 11539 11538 -1
Branches 3839 3838 -1
==========================================
- Hits 10955 10954 -1
Misses 250 250
Partials 334 334
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Hey, please read our AI Contribution Policy and ensure your PR follows it. |
|
I appreciate you pointing that out. I did use AI to help summarize the PR description, but I’ve rewritten it myself now. Also, I’ll keep this in mind for future PRs. Sorry about that. I’m just getting started with open source, so I’d really appreciate any advice on how I can make sure I’m following the project’s expectations properly in future contributions. I enjoy contributing here and would like to keep learning and improving. |
|
Could you please also explain in the description why this is a partial fix? |
|
Updated the PR description to explain why the |
JoshuaKGoldberg
left a comment
There was a problem hiding this comment.
Nice and clean, thanks!
Btw @Arlikhozhaev, it's pretty clear from your PR descriptions you're using AI to write them. They're not generally bad quality (some of the info & explanations have been quite helpful, thank you!) but they're quite verbose. Please be mindful that we have to read every single thing that comes our way - your PR descriptions, the much-lower-quality slop from other folks who're using AI, etc. It's draining. We'd appreciate it if you left out things that are self-evident - even if the AIs add them. ❤️ |
| datasource | package | from | to | | ---------- | -------------------------------- | ------ | ------ | | npm | @typescript-eslint/eslint-plugin | 8.67.0 | 8.69.0 | | npm | @typescript-eslint/parser | 8.67.0 | 8.69.0 | ## [v8.69.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8690-2026-08-31) ##### 🚀 Features - **eslint-plugin:** \[no-misused-promises] add flagUnions option for checkConditionals ([#12603](typescript-eslint/typescript-eslint#12603)) ##### 🩹 Fixes - **eslint-plugin:** \[no-meaningless-void-operator] report void on non-call expressions ([#12727](typescript-eslint/typescript-eslint#12727)) - **eslint-plugin:** \[unified-signatures] compare type parameters by constraint instead of name ([#12741](typescript-eslint/typescript-eslint#12741)) - **eslint-plugin:** \[no-mixed-enums] use scope analysis instead of type checking for merged namespaces ([#12731](typescript-eslint/typescript-eslint#12731)) ##### ❤️ Thank You - Abdu Alim Arlikhozhaev [@Arlikhozhaev](https://github.com/Arlikhozhaev) - Evyatar Daud [@StyleShit](https://github.com/StyleShit) - Josh Goldberg ✨ - wonbeanie [@wonbeanie](https://github.com/wonbeanie) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.69.0) 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. ## [v8.68.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8680-2026-08-24) ##### 🚀 Features - **eslint-plugin:** \[strict-void-return] add fix suggestions ([#12086](typescript-eslint/typescript-eslint#12086)) ##### 🩹 Fixes - **eslint-plugin:** \[no-empty-object-type] ignore suggestions that result in invalid interfaces and export defaults ([#12739](typescript-eslint/typescript-eslint#12739)) - **eslint-plugin:** \[no-floating-promises] setting `ignoreVoid: false` results in false negative in ArrowFunctionExpression ([#12646](typescript-eslint/typescript-eslint#12646)) - **eslint-plugin:** \[no-unnecessary-type-assertion] prevent stack overflow in recursive types ([#12711](typescript-eslint/typescript-eslint#12711)) - **eslint-plugin:** \[unified-signatures] report identical signatures ([#12678](typescript-eslint/typescript-eslint#12678)) - **eslint-plugin:** \[return-await] prevent autofix from breaking code in arrow-functions ([#12707](typescript-eslint/typescript-eslint#12707)) - **eslint-plugin:** \[unified-signatures] deduplicate types in report ([#12656](typescript-eslint/typescript-eslint#12656)) ##### ❤️ Thank You - Evyatar Daud [@StyleShit](https://github.com/StyleShit) - Hugo [@hugop95](https://github.com/hugop95) - Niki [@phaux](https://github.com/phaux) - Younsang Na [@nayounsang](https://github.com/nayounsang) See [GitHub Releases](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.68.0) 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.
In addition to JoshuaKGoldberg's comments, note that the the magic issue-closing string was removed from the issue template, so this wasn't linked to #12143 correctly. Please follow our templates and processes 🙏 |
I think it was intentional, as this only partially fixes it?
|
|
Ah, my bad, then 👍 |
…26956) Port the `unified-signatures` changes from typescript-eslint/typescript-eslint#12656, typescript-eslint/typescript-eslint#12678, and typescript-eslint/typescript-eslint#12741: - Flatten and deduplicate union members in diagnostics, preserving necessary parentheses. - Report identical overload signatures. - Compare type parameter constraint text so distinct constraints such as `extends A` and `extends B` are not unified. Includes the upstream regressions and additional cases checked against ESLint 8.70.1. Parenthesized type nodes are unwrapped to match ESTree, while diagnostics retain Oxc's paired labels. The rule remains diagnostic-only. Validation: focused rule tests, all 62 TypeScript rule tests, and linter clippy passed. `just ready` passed the workspace check but could not finish the all-features test build: the linker ran out of disk space (`errno=28`).

PR Checklist
Overview
unified-signatureswas comparing type parameter constraints by their AST node kind instead of the actual type.That's why
<T extends A>and<T extends B>were considered equal when both A and B were type references, even though they can represent different types.This change reuses the existing
typesAreEqualhelper to compare the constraints instead, and removes the now unnecessaryconstraintsAreEqualhelper.This PR fixes the false positive described in #12143, where overloads with different type parameter constraints could be reported as combinable.
The other case in #12143 is
<T extends string>vs<R extends string>. Those two can be combined, but the rule still compares type parameter names. To fix that we can match parameters by position, and you cannot simply renameTtoRin the source text, becauseTmight be a property name({ T: string }).That is a separate change, so this PR only fixes the
extends Avsextends Bfalse positive.Added tests for type reference constraints and inline union constraints. The existing tests also continue to pass.