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

Immediate keyof operation on intersection of generic mapped types incorrectly results in never type #22291

Closed
kpdonn opened this issue Mar 2, 2018 · 1 comment
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@kpdonn
Copy link
Contributor

kpdonn commented Mar 2, 2018

TypeScript Version: 2.8.0-dev.20180302

Search Terms:
keyof, intersection, mapped type, generic, type parameter, never

Code

type Example1<T extends string, U extends string> = keyof (Record<T, any> & Record<U, any>)
type Result1 = Example1<'x', 'y'>
// Type of Result1 is never but it should be 'x' | 'y'


/**  The additional examples below are just for context */

type Result2 = keyof (Record<'x', any> & Record<'y', any>) 
// Type of Result2 is 'x' | 'y' as expected

type Example3<T extends string> = keyof (Record<T, any>)
type Result3 = Example3<'x' | 'y'>
// Type of Result3 is 'x' | 'y' as expected

type Example4<T extends string, U extends string> = (Record<T, any> & Record<U, any>)
type Result4 = keyof Example4<'x', 'y'>
// Type of Result4 is 'x' | 'y' as expected

type Example5<T, U> = keyof (T & U)
type Result5 = Example5<Record<'x', any>, Record<'y', any>>
// Type of Result5 is 'x' | 'y' as expected

Expected behavior:
Result1 should have a type of 'x' | 'y'

Actual behavior:
Result1 has a type of never

Playground Link:
Link

Related Issues:
Maybe #18538? I read through it but honestly I'm not clear on what is going on in that one so I can't say how related it is.

@ahejlsberg
Copy link
Member

The issue here is that for generic types A and B we should consider keyof (A & B) to be equivalent to keyof A | keyof B. We currently don't implement that transformation. If we did, we would transform keyof (Record<T, any> & Record<U, any>) to keyof Record<T, any> | keyof Record<U, any>, which we already reduce to T | U, the desired result.

@ahejlsberg ahejlsberg self-assigned this Mar 2, 2018
@ahejlsberg ahejlsberg added the Bug A bug in TypeScript label Mar 2, 2018
@ahejlsberg ahejlsberg added this to the TypeScript 2.8 milestone Mar 2, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Mar 2, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

2 participants