Skip to content

Negated Types: Define Extract and Exclude in terms of intersections and negations - #64515

Open
Wesley Wigham (weswigham) wants to merge 1 commit into
weswigham/negated-typesfrom
weswigham/negated-types-extract-exclude-change
Open

Wesley Wigham (weswigham) wants to merge 1 commit into
weswigham/negated-typesfrom
weswigham/negated-types-extract-exclude-change

Conversation

@weswigham

@weswigham Wesley Wigham (weswigham) commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Swaps Extract to T & U and Exclude to T & not U, instead of their current conditional forms.

This isn't a strict improvement - in some ways, it's a step backward. On the extreme end, consider that Extract<T, any> previously yields T, but now yields any - the substitution behavior in conditionals hides the type erasure any (top level or nested) performs.

Copilot AI balanced review requested due to automatic review settings September 28, 2026 20:22
@typescript-automation typescript-automation Bot added Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Sep 28, 2026
@weswigham
Wesley Wigham (weswigham) changed the base branch from main to weswigham/negated-types September 28, 2026 20:27
@weswigham
Wesley Wigham (weswigham) added this pull request to stack #64516 September 28, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

* Construct the type of values in T that are not in U
*/
type Exclude<T, U> = T extends U ? never : T;
type Exclude<T, U> = T & not U;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've played a little bit with something recently and this difference came to my attention:

type S = { kind: "a" | "b"; value: number };
type A = { kind: "a"; value: number };
type B = { kind: "b"; value: number };

type Nested = Exclude<Exclude<S, B>, A>; // { kind: "a" | "b"; value: number; }
type Merged = Exclude<S, A | B>; // never

This PR "fixes" that - both of those reduce down to never (I've checked). I think this makes more sense for an average user, it makes for an interesting test case so it might be worth adding to this PR.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

3 participants