Remot H
Remot H

Reputation: 129

Create an array type containing all distinct keys of provided type

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

Answers (3)

Oblosys
Oblosys

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"]

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.

Upvotes: 1

Kary
Kary

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

Stevie
Stevie

Reputation: 421

type KeyArr<T> = Array<keyof T>;

Note this type allows repetition of keys in the array.

Upvotes: 0

Related Questions