Search code examples
typescripttuplesmapped-types

Why are these two mapped tuple types not equal?


type NumbersTuple = [number, number, number];

type WrapKey<T> = {
  [K in keyof T]: { key: T[K] };
};

type WrappedNumbers1 = WrapKey<NumbersTuple>;

type WrappedNumbers2 = {
  [K in keyof NumbersTuple]: { key: NumbersTuple[K] };
};

Why are WrappedNumbers1 and WrappedNumbers2 not equal? Is it due to how the types are instantiated? I would have expected them to be the same.


Solution

  • This is considered a bug in TypeScript; see microsoft/TypeScript#27995 for more information. When support was added in TypeScript 3.1 for mapped arrays and tuples, it seems this was only done when mapping over keys of generic types like T as in your WrapKey<T> type and not when mapping over keys of specific types like Numbers.

    When you map over keys of specific types you will see the old pre-TS-3.1 behavior where all properties of arrays are mapped over, including length and methods like push(), leading to quite bizarre and mostly useless types. The workaround would involve using an intermediate generic type parameter instead.

    If you want to see this fixed you might want to go to that issue and give it a 👍 or describe your use case if you think it is particularly compelling. It's quite an old issue, though, and it is on the backlog, meaning that it is not slated to be fixed in any upcoming release. So realistically I wouldn't expect to see it addressed anytime soon.