Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to create mapped union type from nested object from object keys

I’m trying to create a type based on a design token JSON file.

The JSON object has the following format:

{
    "Black": {
        "4": { "value": "#f6f6f6" },
        "6": { "value": "#f2f2f2" },
        "10": { "value": "#e8e8e8" },
        "20": { "value": "#d3d3d3" },
        "30": { "value": "#bcbcbc" },
        "40": { "value": "#a7a7a7" },
        "50": { "value": "#909090" },
        "60": { "value": "#7b7b7b" },
        "70": { "value": "#646464" },
        "80": { "value": "#4e4e4e" },
        "90": { "value": "#383838" },
        "100": { "value": "#222222" }
    },
    "Blue": {
        "4": { "value": "#F5F8F8" },
        "8": { "value": "#EBF0F1" },
        "10": { "value": "#E5EBED" },
        "20": { "value": "#CCD9DC" },
        "30": { "value": "#B2C5CA" },
        "40": { "value": "#99B3B9" },
        "50": { "value": "#7F9FA7" },
        "60": { "value": "#668C96" },
        "70": { "value": "#4C7984" },
        "80": { "value": "#336673" },
        "100": { "value": "#004050" }
    },
    "Teal": {
        "20": { "value": "#ccfbf0" },
        "40": { "value": "#99f8e1" },
        "60": { "value": "#66f4d3" },
        "80": { "value": "#33f1c4" },
        "100": { "value": "#00edb5" }
    }
}

I’ve create a union type for the colours using type Color = keyof typeof colorJSON;

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I now want to create another union type for all the nested keys inside the colour objects that are the tint levels e.g. type Tint = '4' | '6' | '8' etc... but can’t work out how to recursively iterate through colours and refer to the keys inside.

Edit

I want the type to automatically update if the JSON file gets more colours added to it so it must iterate through the structure rather than directly referencing the colour names

>Solution :

Consider this example:

const colorJSON = {
  "Black": {
    "4": { "value": "#f6f6f6" },
    "6": { "value": "#f2f2f2" },
    "10": { "value": "#e8e8e8" },
    "20": { "value": "#d3d3d3" },
    "30": { "value": "#bcbcbc" },
    "40": { "value": "#a7a7a7" },
    "50": { "value": "#909090" },
    "60": { "value": "#7b7b7b" },
    "70": { "value": "#646464" },
    "80": { "value": "#4e4e4e" },
    "90": { "value": "#383838" },
    "100": { "value": "#222222" }
  },
  "Blue": {
    "4": { "value": "#F5F8F8" },
    "8": { "value": "#EBF0F1" },
    "10": { "value": "#E5EBED" },
    "20": { "value": "#CCD9DC" },
    "30": { "value": "#B2C5CA" },
    "40": { "value": "#99B3B9" },
    "50": { "value": "#7F9FA7" },
    "60": { "value": "#668C96" },
    "70": { "value": "#4C7984" },
    "80": { "value": "#336673" },
    "100": { "value": "#004050" }
  },
  "Teal": {
    "20": { "value": "#ccfbf0" },
    "40": { "value": "#99f8e1" },
    "60": { "value": "#66f4d3" },
    "80": { "value": "#33f1c4" },
    "100": { "value": "#00edb5" }
  }
}

type Colors = typeof colorJSON

type Values<T> = T[keyof T]

type ColorMap<T extends Record<string, Record<string, unknown>>> = {
  [Prop in keyof T]: keyof T[Prop]

}

type Result = Values<ColorMap<Colors>>

ColorMap – iterates through json keys (Black/Blue/Teal) and obtains union of keys of nested obj.

Values – returns the union of all object values.

Since Object values are unions of keyof json nested objects, compisition of ColorMap and Values gives you the union of all keys of nested objects.

P.S. I don’t think you need to recursively iterate through this object type. However, if you are interested in recursive solutions you can check my article

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading