Reputation: 129
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?
Upvotes: 0
Views: 247
Reputation: 15106
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"]
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.
Upvotes: 1
Reputation: 238
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>
Upvotes: 1
Reputation: 421
type KeyArr<T> = Array<keyof T>;
Note this type allows repetition of keys in the array.
Upvotes: 0