Skip to content

Using keyof with key remapping to exclude index signatures doesn't return known keys #41966

Closed
@tim-stasse

Description

@tim-stasse

TypeScript Version: 4.2.0-dev.20201211

Search Terms:

key remapping
remap index signature
keyof returns number

Code

type Compute<A> = { [K in keyof A]: Compute<A[K]>; } & {};

type EqualsTest<T> = <A>() => A extends T ? 1 : 0;
type Equals<A1, A2> = EqualsTest<A2> extends EqualsTest<A1> ? 1 : 0;

type Filter<K, I> = Equals<K, I> extends 1 ? never : K;

type OmitIndex<T, I extends string | number> = {
  [K in keyof T as Filter<K, I>]: T[K];
};

type IndexObject = { [key: string]: unknown; };
type FooBar = { foo: "hello"; bar: "world"; };

type WithIndex = Compute<FooBar & IndexObject>;   // { [x: string]: {}; foo: "hello"; bar: "world"; } <-- OK
type WithoutIndex = OmitIndex<WithIndex, string>; // { foo: "hello"; bar: "world"; }                  <-- OK

type FooBarKey = keyof FooBar;             // "foo" | "bar"   <-- OK
type WithIndexKey = keyof WithIndex;       // string | number <-- Expected: string 
type WithoutIndexKey = keyof WithoutIndex; // number          <-- Expected: "foo" | "bar"

Expected behavior:

Using keyof with the above remapped type (WithoutIndex) should return the known keys (i.e. "foo" | "bar").

Actual behavior:

While the key remapping in OmitIndex appears to successfully omit the string index signature (e.g. OmitIndex<WithIndex, string> --> { foo: "hello"; bar: "world"; }); using keyof with the resulting type returns number.

Playground Link:

https://www.typescriptlang.org/play?ts=4.2.0-dev.20201211#code/C4TwDgpgBAwg9gWzAV2BAPAQQHxQLxQDeUA2gNJQCWAdlANYQhwBmUmAugFyyIppbl22ANxQAvlABkRMcIBQc0JCgBRAI7IAhgBsAzgBUIu4On24CWbAAoAlPlyYoEAB5pqAE11R9UAPxQARihuAAZ5JWh1LT0sAIAaNgAmc1UNHQMjE0xkp1cIDy8o9MNjWNx-IND5RXBoADFKbTQAJ3QyBIBJFKKY9qgu3LdPQL8oaggANwhm4KgyaoioAHkESmAOjxdTTsH84eNmmgBzKAAfMeQEACNplMI5KFIKGnpGFm8oTS8Gpum2zuwXG8gnksgUiw27hcSyuACsIABjYD4IikBggbgHY5A5DUOjUOAAd2oojBizqcDgACFNDMCMRmJTuAAiAAWEG02jgzNEV1pLMJcGa2ncPPEC1qUAA6mtWZCXCj4EhUBgKdTaVJ+ptnDD4UiRI8oAB6I2okjOTHAQ7UI5AwiyKCMuAs9mc7m8-lQZmC4Wi0lQdAAWkDyzINWUMuArLgqHlzhRKzWcfQkbl2oSWJtBpNqKdLo5XLFfOaAqFIrFEkNVer1aDIaWYfD9UpNOaZEYKPR7zVrdENZrOeZTuZZy9xZHjzroab0tlcfbIE7b1YqbjferOczJ3O1EuNxmU5UzkgSIg7kt1pOM9TMfW2oXS6YK9lt7XxtNu+u037hsPx8RaDnl6w6jsy45yEAA

Related Issues:

#31143
#41383
#38646

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions