Home > other >  TypeScript: get the type of a nested object
TypeScript: get the type of a nested object

Time:04-18

I know that this question may have been answered elsewhere but in case it wasn't, can someone help me get the type of a nested object? We're talking about an object that has multiple other object but all of them look pretty much the same.

const VALUES = {
    currentStreak: {
      display: "Current streak",
      value: currentStreak,
    },
    longestStreak: {
      display: "Longest streak",
      value: longestStreak,
    },
    contributionsThisYear: {
      display: "Contributions this year",
      value: contributionsThisYear,
    },
    totalContributions: {
      display: "Total contributions",
      value: totalContributions,
    },
    currentCompany: {
      display: "Working at",
      value: currentCompany,
    },
}

This would be the object and this is what I've got. It works well for the main keys but I want to have the keys of each object typed as well.

export type Something = {
  [key in keyof typeof VALUES]: { [key: string]: string | number };
};

How do I get the second part right? So that each object has display and value with value being a number or a string.

Sorry if this is a repeat! I'm hoping to understand this once and for all.

CodePudding user response:

You can explicitly define the second part

type DataPoint = {
  display: string;
  value: number;
};

export type Something = {
  [key in keyof typeof VALUES]: DataPoint;
};

CodePudding user response:

If Something is supposed to be a type for VALUES, then you have a problem because you are referencing the object you want to type in its own type declaration.

Unless you have some sort of Enum with string values to extract the keys from, you should be typing the keys as just strings:

interface innerSomething {
  display: string
  value: number | string
}

type Something = {
  [key in string]: innerSomething
}

With an Enum it should be something like this:

enum SomethingKeys {
    currentStreak,
    longestStreak,
    contributionsThisYear,
    totalContributions,
    currentCompany
}

interface innerSomething {
  display: string
  value: number | string
}

type Something = {
  [key in keyof typeof SomethingKeys]: innerSomething;
}

You could also not declare the interface and declare the type of the inner objects in the actual Something declaration like:

enum SomethingKeys {
    currentStreak,
    longestStreak,
    contributionsThisYear,
    totalContributions,
    currentCompany
}

type Something = {
  [key in keyof typeof SomethingKeys]: { display: string, value: number | string };
}

Although using an interface is more readable and maintainable.

  • Related