Skip to content

Omit is breaking in gaurd #32030

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

Closed
stavalfi opened this issue Jun 21, 2019 · 2 comments
Closed

Omit is breaking in gaurd #32030

stavalfi opened this issue Jun 21, 2019 · 2 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@stavalfi
Copy link

stavalfi commented Jun 21, 2019

TypeScript Version: 3.5.2

Search Terms: Omit, guard

Code

type t1 = { a: boolean } & ({ x: number } | { y: string } | {})
const z1: t1 = Date.now() === 123453 ? { a: true, x: 1 } : { a: true }
const z2: Omit<t1, 'a'> = z1
console.log('x' in z2 && z2.x)

Expected behavior:
no errors
Actual behavior:

Error:(235, 29) TS2339: Property 'x' does not exist on type 'never'.

Playground Link:
Link to Playground


If I specify the actual type instead of using Omit, everything is working with no errors:

type t1 = { a: boolean } & ({ x: number } | { y: string } | {})
const z1: t1 = Date.now() === 123453 ? { a: true, x: 1 } : { a: true }
const z2: { x: number } | { y: string } | {} = z1
console.log('x' in z2 && z2.x)
@stavalfi stavalfi changed the title bug: Omit is breaking in gaurd Omit is breaking in gaurd Jun 21, 2019
@jack-williams
Copy link
Collaborator

jack-williams commented Jun 21, 2019

For this to work you need to implement your mapped types in a distributive way. See #28339 for extensive discussion.

TLDR:

// Omit copied from typescript lib.es5.d.ts file
type UnionKeys<T> = T extends any ? keyof T : never
type DistributivePick<T, K extends UnionKeys<T>> = T extends any ? Pick<T, Extract<keyof T, K>> : never;
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type DistributiveOmit<T, K extends UnionKeys<T>> = T extends any ? Omit<T, Extract<keyof T, K>> : never;

type t1 = { a: boolean } & ({ x: number } | { y: string } | {})
const z1: t1 = Date.now() === 123453 ? { a: true, x: 1 } : { a: true }
const z2: DistributiveOmit<t1, 'a'> = z1
console.log('x' in z2 && z2.x)

@stavalfi
Copy link
Author

Okay. You gave me a lot to learn before I can respond.

If this is working as Intended, close this issue.

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Jun 26, 2019
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

3 participants