如何从对象键的嵌套对象创建映射联合类型

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

我正在尝试创建一个基于设计标记 JSON 文件的类型。

JSON 对象具有以下格式:

{
    "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 Color = keyof typeof colorJSON;

为颜色创建了一个联合类型

我现在想为作为色调级别的颜色对象内的所有嵌套键创建另一个联合类型,例如type Tint = '4' | '6' | '8' etc... 但无法弄清楚如何递归地遍历颜色并引用其中的键。

---编辑---

如果 JSON 文件添加了更多颜色,我希望类型自动更新,因此它必须遍历结构而不是直接引用颜色名称

您可以使用括号表示法导航到嵌套对象的类型并使用 keyof,并在不同颜色之间切换:

type ColorJSON = typeof colorJSON;
type Color = keyof ColorJSON;
type Tint = keyof ColorJSON['Black'] | keyof ColorJSON['Blue'] | keyof ColorJSON['Teal']

对于这个特定的数据,您可以省略青色,因为它的键已经包含在蓝色中。

考虑这个例子:

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 - 遍历 json 个键 (Black/Blue/Teal) 并获得嵌套对象的键的并集。

Values - returns 所有对象值的并集。

由于对象值是 json 嵌套对象的键的并集,ColorMapValues 的组合为您提供了嵌套对象的所有键的并集。

P.S。我认为您不需要递归遍历此对象类型。但是,如果您对递归解决方案感兴趣,可以查看我的 article