'Typescript convert interface keys to nested tuples/array of strings

Not sure if this is possible... but I am trying to convert an interface to tuples using the keys of the interface.

Interface:

interface User {
  _id: string;
  first_name: string;
  last_name: string;
  address: {
    firstLine: string;
    secondLine: string;
    state: string;
    zip: string;
    details: {
      active: boolean;
      primary: boolean;
    }
  }
}

The new type should allow me to create an array as such:

const args: UserKeysTuple = ["_id", ["address", ["zip", "details": ["active"]]];

Order does not matter.



Solution 1:[1]

This is possible to some degree using mapped types:

type KeyTuple<T> = {
  [Key in keyof T]:
    T[Key] extends object ?
      T[Key] extends Date ?
        Key :
        NestedTuple<T, Key> :
      Key
}[keyof T][]
type NestedTuple<T, K extends keyof T> = [K, KeyTuple<T[K]>];

type UserKeysTuple = KeyTuple<User>;

This has some limitations though, among them:

  • It's a mess; see also the special case for Date because it is an object but usually is treated like a primitive
  • This does not check for duplicates, so a key could be listed multiple times without error

Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 H.B.