【问题标题】:How to create mapped union type from nested object from object keys如何从对象键的嵌套对象创建映射联合类型
【发布时间】:2022-01-03 19:46:18
【问题描述】:

我正在尝试基于设计令牌 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 文件添加了更多颜色,我希望类型自动更新,因此它必须遍历结构而不是直接引用颜色名称

【问题讨论】:

标签: typescript union-types mapped-types


【解决方案1】:

考虑这个例子:

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)并获得嵌套 obj 的键的联合。

Values - 返回所有对象值的并集。

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 这是大部分的方式,我唯一的问题是我不想单独指定每个键,因为这个 JSON 文件将添加额外的颜色,我不想手动更新类型
    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 2020-02-08
    • 2021-05-25
    • 2021-12-11
    • 2023-01-13
    • 2020-02-19
    • 1970-01-01
    • 2013-08-01
    相关资源
    最近更新 更多