Typescript: Key Remapping and keyof modifier

Created on 29 Sep 2020  Β·  2Comments  Β·  Source: microsoft/TypeScript



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:

Bug Fix Available

Most helpful comment

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.

All 2 comments

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.

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fwanicka picture fwanicka  Β·  3Comments

manekinekko picture manekinekko  Β·  3Comments

CyrusNajmabadi picture CyrusNajmabadi  Β·  3Comments

jbondc picture jbondc  Β·  3Comments

wmaurer picture wmaurer  Β·  3Comments