Skip to content

keyof "a" behaves differently when using a type parameter #23345

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
ghost opened this issue Apr 11, 2018 · 3 comments
Closed

keyof "a" behaves differently when using a type parameter #23345

ghost opened this issue Apr 11, 2018 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ghost
Copy link

ghost commented Apr 11, 2018

TypeScript Version: 2.9.0-dev.20180411

Code

type A = { [P in keyof "a"]?: boolean }; // { padStart?: boolean | undefined, ... }
type Indirect<T> = { [P in keyof T]?: boolean };
type B = Indirect<"a">; // "a"

declare const a: A;
const b: B = a; // Error

Expected behavior:

No error. B is the same as A.

Actual behavior:

Error: B is the string literal type "a".

@mhegazy mhegazy added the Bug A bug in TypeScript label Apr 12, 2018
@mhegazy mhegazy added this to the TypeScript 2.9 milestone Apr 12, 2018
@mhegazy mhegazy modified the milestones: TypeScript 2.9, Future Apr 26, 2018
@ahejlsberg
Copy link
Member

This is working as intended. When instantiating a homomorphic mapped type such as { [P in keyof T]?: boolean } we distribute over union types and leave non-object types unchanged. For example, Indirect<{ x: string } | undefined> is resolved as Indirect<{ x: string }> | undefined. For this reason, Indirect<"a"> is simply "a".

@ahejlsberg ahejlsberg added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Bug A bug in TypeScript labels Jun 3, 2018
@mhegazy mhegazy removed this from the Future milestone Jun 4, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@aleclarson
Copy link

aleclarson commented Sep 13, 2018

we distribute over union types and leave non-object types unchanged

What does it mean to "distribute over union types"?

Also, it seems that as long as I avoid using keyof inside the generic "mapped type" declaration, I can avoid this footgun. See here: https://goo.gl/DakrYm

What's the practical benefit of making keyof behave differently when inside a generic "mapped type"? Or is it simply a consequence of the current implementation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants