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

Key Remapping and keyof modifier #40833

Closed
shauns opened this issue Sep 29, 2020 · 2 comments · Fixed by #40837
Closed

Key Remapping and keyof modifier #40833

shauns opened this issue Sep 29, 2020 · 2 comments · Fixed by #40837
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@shauns
Copy link

shauns commented Sep 29, 2020

TypeScript Version: 4.1.0-beta

Using the new key remapping feature, with a remapped object with never keys (for omitting). Passing the remapped object to keyof returns never, instead of the keys from the remapped object. Checks with the remapped object itself work as expected - its only when then using keyof do they fail.

Search Terms:

  • key remapping
  • keyof with never

Code

type Example = {foo: string, bar: number}
  
type PickByValueType<T, U> = {
  [K in keyof T as T[K] extends U ? K : never]: T[K]
}

type T1 = PickByValueType<Example, string>
const e1: T1 = {
    foo: "hello"
}
type T2 = keyof T1
const e2: T2 = "foo"

Expected behavior:

keyof T1 should be "foo"

Actual behavior:

keyof T1 is never

T1 correctly picks out the expected keys based on the condition check, but when ran through keyof it seems to lose the "set" keys.

Playground Link:

https://www.typescriptlang.org/play?ts=4.1.0-pr-40336-88&ssl=4&ssc=41&pln=4&pc=46#code/C4TwDgpgBAogHgQwLZgDbQLxQN4DMD2+AXFAM7ABOAlgHYDmANFAEYIUk0CuSzEFAvgCgoUQaEhQAClQDGAawBCIAGoJUnCABVwEADyamAVQB8ULNmFQA2gGkotKHIgh8uKJqgJS72wF0oEHDAEDQAJt6GUAD8UHYcEABufL4kmn6CQmI67gCMZlKyiipqGtqQuvDIaBBM5NT0xoIy+DTkATmpeeaWIgTEUABEABYQqKj4AxlZEpoATPlOLm6aOU0tbRCzqfNYA32TQA

Related Issues:

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Sep 29, 2020
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 4.1.1 milestone Sep 29, 2020
@ahejlsberg
Copy link
Member

Ah, the issue here is that the conditional type in the as clause is not distributive, so when applied to a union type (which we do in getIndexType) it isn't applied to each key individually. A workaround is this:

type PickByValueType<T, U> = {
  [K in keyof T as K extends K ? T[K] extends U ? K : never : never]: T[K]
}

But of course it should work without the explicit distribution trick.

@shauns
Copy link
Author

shauns commented Sep 30, 2020

Thanks for sharing the workaround @ahejlsberg ! I see there's an open PR for a fix, so I hope the bug report was useful. And thanks for the addition of the feature -- I've already two scenarios where it's proved useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants