Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omitting a property on a discriminated union type #54525

Closed
Trekiros opened this issue Jun 5, 2023 · 8 comments
Closed

Omitting a property on a discriminated union type #54525

Trekiros opened this issue Jun 5, 2023 · 8 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@Trekiros
Copy link

Trekiros commented Jun 5, 2023

Bug Report

When using Omit on a discriminated union type, the properties unique to each "branch" of the union type are lost.

🔎 Search Terms

Omit, union, discriminated union

🕗 Version & Regression Information

Tested on TypeScript 4.8.4 and on the nightly version (June 5th, 2023)

⏯ Playground Link

demo

Alternative demo (a different way to do discriminated unions, which is also affected)

💻 Code

type T = {
    name: string,
    type: 1,
    prop1: string,
} | {
    name: string,
    type: 2,
    prop2: string,
}

type T2 = Omit<T, 'name'>

🙁 Actual behavior

T2 is interpreted as such by TypeScript:

type T2 = {
    type: 1 | 2;
}

And the following object is seen as invalid:

const obj: T2 = {
    type: 2,
    prop2: 'abcd', // "prop2 does not exist on type T2"
}

🙂 Expected behavior

T2 should be interpreted like this instead:

type T2 = {
    type: 1;
    prop1: string;
} | {
    type: 2;
    prop2: string;
}

And the object described above should be seen as valid.

@MartinJohns
Copy link
Contributor

This is unfortunately working as intended. Omit does not distribute over the union. There are many implementations of a distributive omit out there, just search for it using "distributive omit". See also #54451.

@nurulakbaral
Copy link

You can create your own Omit with Distributive Conditional Types:

type TheOmit<T, K extends string | number | symbol> = T extends any ? Omit<T, K> : never

@MartinJohns
Copy link
Contributor

@nurulakbaral Be aware that this version will not warn you if you mistype the property name, while the version suggested in #54451 will error, but only allows to omit properties common to all types of the union.

@nurulakbaral
Copy link

@nurulakbaral Be aware that this version will not warn you if you mistype the property name, while the version suggested in #54451 will error, but only allows to omit properties common to all types of the union.

type TheOmit<T, K extends keyof T> = T extends any ? Omit<T, K> : never

How about this?

@jcalz
Copy link
Contributor

jcalz commented Jun 5, 2023

Duplicate of #31501

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Jun 5, 2023
@microsoft-github-policy-service

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow or the TypeScript Discord community.

@typescript-bot
Copy link
Collaborator

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow or the TypeScript Discord community.

1 similar comment
@microsoft-github-policy-service

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow or the TypeScript Discord community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants