Skip to content

Conversation

@mdm317
Copy link
Contributor

@mdm317 mdm317 commented Jan 29, 2025

PR Checklist

Overview

even cases where they're deeply equal, but declared as different object types.

This feature seems to overlap with this rule no-duplicate-type-constituents so I'm not sure whether to include it.
For now, I'll remove it and proceed.

deeply equal

type ShallowEqual = number | number;
type DeepEqual = { a: string } | { a: string };

Union
If x is assignable to y, then in the union x∣y, x is redundant and can be removed.
However, due to TypeScript's Excess Property Checks feature, this logic did not work as expected.

For example, consider the union type { a: 1 } | { a: 1, b: 1 }. Since { a: 1, b: 1 } is assignable to { a: 1 }
So { a: 1, b: 1 } becomes redundant and can be removed.

However, if { a: 1, b: 1 } is removed, the remaining type { a: 1 } exhibits different behavior when declaring values.
For example, { a: 1 } alone can only be assigned to variables of type { a: 1 }, whereas { a: 1 } | { a: 1, b: 1 } allows the declaration of both { a: 1 } and { a: 1, b: 1 }

Example code

type Foo = { a: 1 } | { a: 1, b: 1 }
const foo: Foo = { a: 1 }
const bar: Foo = { a: 1, b: 1 }

type Foo2 = { a: 1 } 
const foo2: Foo2 = { a: 1 }
const bar2: Foo2 = { a: 1, b: 1 } //error

So, before checking whether one type is assignable to another, I first verified that both objects have the same set of keys. Only then did I proceed with the assignability check.
For A | B, i checks if A and B have the same keys. If they do, it then checks assignability.

Union Types with Intersection Types

  • Union with a Single Intersection:
    • If a union type contains an intersection, like A | (B & C & D), the intersection (B & C & D) is treated as a single object type.
  • Union within an Intersection:
    • If an intersection includes a union, like A | (B & (C | D)), TypeScript simplifies the intersection into a union of intersections. B & (C | D) is equivalent to B & C | B & D,
    • This means the assignability check becomes: Is A assignable to (B & C) | (B & D)

Intersection
Unlike union types, intersection types did not need excess property checks.
A & B in this case if A is assignable to B B is rebundant.

  • If there is no union type within the intersection, I proceed the assignability check. A & B
  • If there is union type, I check if every type in the union is compatible with the intersection and follows the same rules.
  • A & ( B | C)
A >= B, A >= C  Then  A >= (B | C)
B >= A, C >= A  Then   (B | C) >= A

@typescript-eslint
Copy link
Contributor

Thanks for the PR, @mdm317!

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.

@netlify
Copy link

netlify bot commented Jan 29, 2025

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit acb39d8
🔍 Latest deploy log https://app.netlify.com/projects/typescript-eslint/deploys/690ec977b986270008806f99
😎 Deploy Preview https://deploy-preview-10744--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 99 (🟢 up 3 from production)
Accessibility: 97 (no change from production)
Best Practices: 100 (no change from production)
SEO: 92 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link

nx-cloud bot commented Jan 29, 2025

View your CI Pipeline Execution ↗ for commit acb39d8

Command Status Duration Result
nx test eslint-plugin --coverage=false ✅ Succeeded 5m 17s View ↗
nx run-many -t lint ✅ Succeeded 3m 29s View ↗
nx run-many -t typecheck ✅ Succeeded 2m 14s View ↗
nx test eslint-plugin-internal --coverage=false ✅ Succeeded 4s View ↗
nx run types:build ✅ Succeeded 5s View ↗
nx run integration-tests:test ✅ Succeeded 6s View ↗
nx test typescript-estree --coverage=false ✅ Succeeded 2s View ↗
nx run generate-configs ✅ Succeeded 6s View ↗
Additional runs (29) ✅ Succeeded ... View ↗

☁️ Nx Cloud last updated this comment at 2025-11-08 04:52:01 UTC

@codecov
Copy link

codecov bot commented Jan 29, 2025

Codecov Report

❌ Patch coverage is 92.07746% with 45 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.61%. Comparing base (ea2ee6b) to head (acb39d8).
⚠️ Report is 26 commits behind head on main.

Files with missing lines Patch % Lines
...plugin/src/rules/no-redundant-type-constituents.ts 92.38% 42 Missing and 1 partial ⚠️
...escript-estree/src/semantic-or-syntactic-errors.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #10744      +/-   ##
==========================================
- Coverage   90.66%   90.61%   -0.05%     
==========================================
  Files         518      518              
  Lines       52435    52733     +298     
  Branches     8686     8771      +85     
==========================================
+ Hits        47541    47785     +244     
- Misses       4880     4933      +53     
- Partials       14       15       +1     
Flag Coverage Δ
unittest 90.61% <92.07%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ages/eslint-plugin/src/rules/no-unsafe-argument.ts 93.24% <100.00%> (ø)
...nt-plugin/src/rules/related-getter-setter-pairs.ts 100.00% <ø> (ø)
...escript-estree/src/semantic-or-syntactic-errors.ts 2.32% <0.00%> (ø)
...plugin/src/rules/no-redundant-type-constituents.ts 93.41% <92.38%> (-4.23%) ⬇️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JoshuaKGoldberg
Copy link
Member

👋 Ping @mdm317, are you planning on un-draft ing this soon? We'd prefer not to keep drafts around for too long in case someone else would want to send one too.

@mdm317
Copy link
Contributor Author

mdm317 commented Mar 3, 2025

Sorry for the delay. This issue was more challenging than I expected.
I'll try to finish it within two days. If it takes longer, I'll close the PR and reopen it once it's resolved.
Moving forward, if I anticipate a delay, I'll close it first and reopen it when it's ready.

@mdm317 mdm317 marked this pull request as ready for review March 5, 2025 19:03
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK! Sorry for the delay in reviewing. This is a really tricky one 😅.

I think the feature request is a lot trickier than the test cases here currently capture. It'll have to handle a lot of cases, including optional properties, interfaces extending each other, and so on. I suspect the core implementation will have to adjust a bunch - so left a few suggestions on how to reduce the amount of work done. Hope it's helpful, and let me know if you have questions! 🙌

@JoshuaKGoldberg JoshuaKGoldberg added the awaiting response Issues waiting for a reply from the OP or another party label Mar 17, 2025
@mdm317
Copy link
Contributor Author

mdm317 commented Mar 20, 2025

Thank you for your review!
I'll try implementing it according to your suggestion.

@mdm317 mdm317 marked this pull request as ready for review November 9, 2025 08:51
@JoshuaKGoldberg JoshuaKGoldberg self-requested a review November 10, 2025 15:25
@JoshuaKGoldberg JoshuaKGoldberg removed the awaiting response Issues waiting for a reply from the OP or another party label Nov 10, 2025
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳 Whoohoo! Thanks so much for bearing with me on reviews and making so many refactors. This is a lot of code by necessity, but it's roughly as clean as I think it can get. Nice job!

Just to be safe I'd like to get another review from someone on @typescript-eslint/triage-team if possible (though we are swamped, and I don't want to wait beyond the end of this month).

@JoshuaKGoldberg JoshuaKGoldberg added the 1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge label Nov 18, 2025
checker: ts.TypeChecker,
depth = 0,
): boolean {
if (depth > 10) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another way to do this is to keep track of "seen" types.
If the type is already in the set then it's recursive.

@bradzacher bradzacher merged commit 2ffb168 into typescript-eslint:main Nov 23, 2025
67 of 69 checks passed
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Nov 24, 2025
| datasource | package                          | from   | to     |
| ---------- | -------------------------------- | ------ | ------ |
| npm        | @typescript-eslint/eslint-plugin | 8.47.0 | 8.48.0 |
| npm        | @typescript-eslint/parser        | 8.47.0 | 8.48.0 |


## [v8.48.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8480-2025-11-24)

##### 🚀 Features

- **eslint-plugin:** \[no-redundant-type-constituents] use assignability checking for redundancy checks ([#10744](typescript-eslint/typescript-eslint#10744))

##### 🩹 Fixes

- **typescript-estree:** disallow binding patterns in parameter properties ([#11760](typescript-eslint/typescript-eslint#11760))
- **eslint-plugin:** \[consistent-generic-constructors] ignore when constructor is  typed array ([#10477](typescript-eslint/typescript-eslint#10477))

##### ❤️ Thank You

- Dima Barabash [@dbarabashh](https://github.com/dbarabashh)
- JamesHenry [@JamesHenry](https://github.com/JamesHenry)
- Josh Goldberg
- mdm317 [@gen-ip-1](https://github.com/gen-ip-1)

You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Nov 24, 2025
| datasource | package                          | from   | to     |
| ---------- | -------------------------------- | ------ | ------ |
| npm        | @typescript-eslint/eslint-plugin | 8.47.0 | 8.48.0 |
| npm        | @typescript-eslint/parser        | 8.47.0 | 8.48.0 |


## [v8.48.0](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8480-2025-11-24)

##### 🚀 Features

- **eslint-plugin:** \[no-redundant-type-constituents] use assignability checking for redundancy checks ([#10744](typescript-eslint/typescript-eslint#10744))

##### 🩹 Fixes

- **typescript-estree:** disallow binding patterns in parameter properties ([#11760](typescript-eslint/typescript-eslint#11760))
- **eslint-plugin:** \[consistent-generic-constructors] ignore when constructor is  typed array ([#10477](typescript-eslint/typescript-eslint#10477))

##### ❤️ Thank You

- Dima Barabash [@dbarabashh](https://github.com/dbarabashh)
- JamesHenry [@JamesHenry](https://github.com/JamesHenry)
- Josh Goldberg
- mdm317 [@gen-ip-1](https://github.com/gen-ip-1)

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
Copy link
Member

This change is very exciting, but has a lot more edge cases and implications than we realized 😬. Reverted in #11812 - which has a list of issues. #7742 is now open again with a note.

jimmy-zhening-luo added a commit to jimmy-zhening-luo/linted-defaults that referenced this pull request Dec 2, 2025
…; re-enable the bugged lint rule:

eslint-plugin: revert: [no-redundant-type-constituents] use assignability checking for redundancy checks (typescript-eslint/typescript-eslint#10744) (typescript-eslint/typescript-eslint#11812)
jimmy-zhening-luo added a commit to jimmy-zhening-luo/linted that referenced this pull request Dec 2, 2025
…; re-enable the bugged lint rule:

- eslint-plugin: revert: [no-redundant-type-constituents] use assignability checking for redundancy checks (typescript-eslint/typescript-eslint#10744) (typescript-eslint/typescript-eslint#11812)
- chore: update pkg
ch4og pushed a commit to csmplay/mapban that referenced this pull request Dec 4, 2025
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
| [@typescript-eslint/eslint-plugin](https://typescript-eslint.io/packages/eslint-plugin) ([source](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)) | [`8.47.0` -> `8.48.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/8.47.0/8.48.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2feslint-plugin/8.48.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2feslint-plugin/8.47.0/8.48.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |
| [@typescript-eslint/parser](https://typescript-eslint.io/packages/parser) ([source](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)) | [`8.47.0` -> `8.48.1`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.47.0/8.48.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.48.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.47.0/8.48.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint (@&#8203;typescript-eslint/eslint-plugin)</summary>

### [`v8.48.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8481-2025-12-02)

[Compare Source](typescript-eslint/typescript-eslint@v8.48.0...v8.48.1)

##### 🩹 Fixes

- **eslint-plugin:** \[restrict-template-expressions] check base types in allow list ([#&#8203;11764](typescript-eslint/typescript-eslint#11764), [#&#8203;11759](typescript-eslint/typescript-eslint#11759))
- **eslint-plugin:** honor ignored base types on generic classes ([#&#8203;11767](typescript-eslint/typescript-eslint#11767))
- **eslint-plugin:** \[consistent-type-exports] check value flag before resolving alias ([#&#8203;11769](typescript-eslint/typescript-eslint#11769))

##### ❤️ Thank You

- Josh Goldberg
- OleksandraKordonets
- SangheeSon [@&#8203;Higangssh](https://github.com/Higangssh)
- tao

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.48.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8480-2025-11-24)

[Compare Source](typescript-eslint/typescript-eslint@v8.47.0...v8.48.0)

##### 🚀 Features

- **eslint-plugin:** \[no-redundant-type-constituents] use assignability checking for redundancy checks ([#&#8203;10744](typescript-eslint/typescript-eslint#10744))

##### 🩹 Fixes

- **typescript-estree:** disallow binding patterns in parameter properties ([#&#8203;11760](typescript-eslint/typescript-eslint#11760))
- **eslint-plugin:** \[consistent-generic-constructors] ignore when constructor is  typed array ([#&#8203;10477](typescript-eslint/typescript-eslint#10477))

##### ❤️ Thank You

- Dima Barabash [@&#8203;dbarabashh](https://github.com/dbarabashh)
- JamesHenry [@&#8203;JamesHenry](https://github.com/JamesHenry)
- Josh Goldberg
- mdm317 [@&#8203;gen-ip-1](https://github.com/gen-ip-1)

You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint (@&#8203;typescript-eslint/parser)</summary>

### [`v8.48.1`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8481-2025-12-02)

[Compare Source](typescript-eslint/typescript-eslint@v8.48.0...v8.48.1)

This was a version bump only for parser to align it with other projects, there were no code changes.

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.48.0`](https://github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8480-2025-11-24)

[Compare Source](typescript-eslint/typescript-eslint@v8.47.0...v8.48.0)

This was a version bump only for parser to align it with other projects, there were no code changes.

You can read about our [versioning strategy](https://typescript-eslint.io/users/versioning) and [releases](https://typescript-eslint.io/users/releases) on our website.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4xNC4yIiwidXBkYXRlZEluVmVyIjoiNDIuMTQuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://git.csmpro.ru/csmpro/mapban/pulls/57
Co-authored-by: Renovate Bot <renovate@csmpro.ru>
Co-committed-by: Renovate Bot <renovate@csmpro.ru>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1 approval >=1 team member has approved this PR; we're now leaving it open for more reviews before we merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: [no-redundant-type-constituents] Use assignability checking for redundancy checks

4 participants