You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决TypeScript中嵌套对象属性访问的类型匹配问题

问题

我实现了一个TypeScript函数,接收primary.500这类格式的字符串颜色参数,返回对应的hex颜色值。所有颜色存储在PALETTE常量对象中,我通过点号拆分字符串,将第一个元素作为PALETTE的键、第二个元素作为子对象的键来取值,但在colorValue = PALETTE[key][value]行出现TypeScript类型错误,该如何修复?

原代码如下:

const PALETTE = {
  common: {
    white: "#fff",
    black: "#000",
  },
  primary: {
    500: "#222",
    700: "#333",
  },
  secondary: {
    500: "#444",
    700: "#555",
  },
} as const;

type Palette = typeof PALETTE;

type ColorVariant = {
  [K in keyof Palette]: `${K}.${Exclude<keyof Palette[K], symbol>}`;
}[keyof Palette];

type ColorVariantKey = {
  [K in keyof Palette]: Exclude<keyof Palette[K], symbol>;
}[keyof Palette];

type GetColor = ColorVariant | "inherit";

const getColor = (color: GetColor) => {
  let colorValue = "inherit";

  if (color !== "inherit") {
    const [key, value] = color.split(".") as [keyof Palette, ColorVariantKey];
    colorValue = PALETTE[key][value]; // 此处出现TypeScript类型错误
  }

  return colorValue;
};

getColor("common.white");
getColor("primary.500");
getColor("secondary.700");

解决方案

错误原因

TypeScript无法确保拆分后的key和value是匹配的:ColorVariantKey是所有子键的联合类型("white" | "black" | "500" | "700"),当key为common时,TypeScript无法排除value是500的可能性,而common对象并没有500这个键,因此触发类型不兼容错误。

修复方式

方式1:类型断言(快速解决)

直接对取值结果做类型断言,告诉TypeScript该操作是安全的:

const getColor = (color: GetColor) => {
  let colorValue = "inherit";

  if (color !== "inherit") {
    const [key, value] = color.split(".") as [keyof Palette, ColorVariantKey];
    // 断言为具体的颜色值类型
    colorValue = PALETTE[key][value] as (typeof PALETTE)[keyof typeof PALETTE][keyof (typeof PALETTE)[keyof typeof PALETTE]];
  }

  return colorValue;
};

如果只需要确保是字符串类型,也可以简化为:

colorValue = PALETTE[key][value] as string;

方式2:类型守卫(更严谨)

通过分支判断缩小key的范围,让TypeScript明确value对应的子键类型:

const getColor = (color: GetColor) => {
  let colorValue = "inherit";

  if (color !== "inherit") {
    const [key, value] = color.split(".") as [keyof Palette, ColorVariantKey];
    
    if (key === "common") {
      colorValue = PALETTE.common[value as keyof typeof PALETTE.common];
    } else if (key === "primary") {
      colorValue = PALETTE.primary[value as keyof typeof PALETTE.primary];
    } else if (key === "secondary") {
      colorValue = PALETTE.secondary[value as keyof typeof PALETTE.secondary];
    }
  }

  return colorValue;
};

方式3:泛型重构(最安全)

使用泛型让TypeScript跟踪key和value的对应关系,从根源上避免类型不匹配:

const PALETTE = {
  common: {
    white: "#fff",
    black: "#000",
  },
  primary: {
    500: "#222",
    700: "#333",
  },
  secondary: {
    500: "#444",
    700: "#555",
  },
} as const;

type Palette = typeof PALETTE;
type ColorVariant = `${keyof Palette}.${keyof Palette[keyof Palette]}`;
type GetColor = ColorVariant | "inherit";

const getColor = <K extends keyof Palette, V extends keyof Palette[K]>(color: `${K}.${V}` | "inherit") => {
  if (color === "inherit") return "inherit";
  const [key, value] = color.split(".") as [K, V];
  return PALETTE[key][value];
};

getColor("common.white");
getColor("primary.500");
getColor("secondary.700");

这种方式下,TypeScript会严格校验输入的字符串格式,甚至能在你输入错误的键值对时给出提示。


内容的提问来源于stack exchange,提问作者qweezz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:07:03