0

I want to create a generic type, say

type KeyArr<T>

that will contain the union of T's key permutations

For example:

type foo = KeyArr<{a:1, b:2}>;

should be the same as

type foo = ['a', 'b'] | ['b', 'a'];

Is this achievable?

Remot H
  • 119
  • 2
  • 10
  • There's a reasonably clean solution that gives you a union of all permutations, i.e. `['a', 'b'] | ['b', 'a']` instead of just `['a', 'b']`, which kind of makes sense as properties are not ordered in types. If you're interested in this, I can write it up. – Oblosys Apr 06 '21 at 19:19
  • I would absolutely love it if it is not too much of a hassle – Remot H May 09 '21 at 07:51
  • That is quite a late response! But it turns out I still had this lying around in my browser history: https://tsplay.dev/NVnDqN – Oblosys May 09 '21 at 15:17
  • This is just fantastic! Precisely what I was looking for. Please post an answer to this question so I could confirm it! – Remot H May 11 '21 at 13:19

3 Answers3

1

In general - yes, it's possible. If having an Array type that accepts every key from object is sufficient in your case, take a look at code below. If you need Tuple type it's more complex, have a look at this thread

type KeyArr<T extends object> = Array<keyof T>
Kary
  • 229
  • 1
  • 8
1

Computing a union of all permutation tuples is actually a bit simpler than converting a union to a single tuple. A recursive mapped type with a conditional to return [] rather than never on empty objects, will do the job:

type KeyArr<T> =
  keyof T extends []
  ? []
  : {[K in keyof T]: [K, ...KeyArr<Omit<T,K>>]}[keyof T]

type Foo1 = KeyArr<{}>               // []
type Foo2 = KeyArr<{a:1, b:2}>       // ["a", "b"] | ["b", "a"]
type Foo3 = KeyArr<{a:1, b:2, c: 3}> // ["a", "b", "c"] | ["a", "c", "b"] | ["b", "a", "c"] | ["b", "c", "a"] | ["c", "a", "b"] | ["c", "b", "a"]

TypeScript playground

The union types will quickly get really big though. For an object with 8 properties, the union has 40320 members and TypeScript gets noticeably slow, and for 9 properties (which would create a union of 362880) it fails altogether.

Oblosys
  • 14,468
  • 3
  • 30
  • 38
0
type KeyArr<T> = Array<keyof T>;

Note this type allows repetition of keys in the array.

YohaiM
  • 383
  • 2
  • 9