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

T[K] should be never when T is never #23005

Closed
kpdonn opened this issue Mar 29, 2018 · 2 comments
Closed

T[K] should be never when T is never #23005

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

Comments

@kpdonn
Copy link
Contributor

kpdonn commented Mar 29, 2018

TypeScript Version: 2.9.0-dev.20180329

Search Terms:
indexed access type, index type never

Code

type Example<T extends Record<'a', string>> = T['a']

type Result1 = Example<{ a: "x" } | { a: "y" }> // type of Result1 is "x" | "y"
type Result2 = Example<{ a: "x" }> // type of Result2 is  "x"
type Result3 = Example<never> // type of Result3 is any 

Expected behavior:
Type of Result3 to be never

Actual behavior:
Type of Result3 is any

Playground Link:
Link

Workaround
Now that #22042 is resolved this can be worked around with

type Workaround<T extends Record<'a', string>> = T[(keyof T) & 'a']
type Result4 = Workaround<never> // type of Result4 is never in typescript@next

Related Issues:
Similar to #22042. That was about type of T[K] when K was never while this is about when T is never.

@agentcooper
Copy link
Contributor

type Example<T> = T extends Record<'a', string> ? T['a'] : never;

maybe?

@kpdonn
Copy link
Contributor Author

kpdonn commented Mar 31, 2018

That actually only works because of how conditional types work with type parameters. It distributes the condition over any unions, and never is treated as an empty union. So it actually isn't that never is failing the condition there, it's that the condition is never even tested. It would actually pass the condition and end up as any if the condition is tested.

You can see that's what is happening more clearly with something like

type Example2<T> = T extends Record<'a', string> ? true : false;
type Result2 = Example2<never> // never instead of either true or false

And if you get rid of the distribution behavior by wrapping the two sides in [] you can see you still get any:

type Example3<T extends Record<'a', string>> = [T] extends [Record<'a', string>] ? T["a"] : never;
type Result3 = Example3<never> // any

@mhegazy mhegazy added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Apr 2, 2018
@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript and removed In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Aug 6, 2018
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.1 milestone Aug 6, 2018
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Aug 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

5 participants