Home > Blockchain >  How can we get keys of an object?
How can we get keys of an object?

Time:10-30

Suppose We have an interface A that has two properties:

interface A {
  a: string;
  b: {
    c: string;
  };
}

type Key = ???????

const test: Key[] = ['a', 'b', 'c'];

so how can we define and make it work ?

Playground link here.

CodePudding user response:

You can have an util type that get's all the keys of the object recursively, something like:

interface A {
  a: string;
  b: {
    c: string;
  };
}


// create a type that gets keys recursively
type RecursiveKeyOf1<TObj extends object> = {
  [TKey in keyof TObj & (string | number)]: TObj[TKey] extends object
    ? `${TKey}` | `${RecursiveKeyOf<TObj[TKey]>}`
    : `${TKey}`;
}[keyof TObj & (string | number)];

// create a type for the object's keys
type ObjectKeys = RecursiveKeyOf1<A> // "a" | "b" | "c"

const keys: ObjectKeys[] = ["a", "b", "c"]

CodePudding user response:

You can define a conditional type that applies the keyof type operator to all objects and recursively in those objects' properties. For example:

type NestedKeyof<T> = T extends object ?
  { [K in keyof T]: K | NestedKeyof<T[K]> }[keyof T]
  : never

This works for your example code:

interface A {
  a: string;
  b: {
    c: string;
  };
}

type Key = NestedKeyof<A>;
// type Key = "a" | "b" | "c"

const test: Key[] = ['a', 'b', 'c'];

There are always caveats, so you should test this against your real use cases. For instance, if you write NestedKey<Tree> with interface Tree { prop: Tree }, you'll get a circularity warning (which makes sense).

Playground link to code

  • Related