Typescript如何对嵌套对象按key索引解决类型不兼容问题
问题根因
你遇到的类型报错核心原因是 Object.keys() 方法在TypeScript的默认类型定义中返回的是 string[] 类型,并不会自动推导为目标对象的键字面量联合类型。因此直接用返回的字符串作为索引访问对象属性时,TypeScript无法确认该字符串是目标对象的合法键,就会抛出类型不兼容的错误。
解决方案
方案1:通用工具函数(推荐,不丢失类型精度)
先写一个通用的类型安全的objectKeys工具函数,覆盖默认Object.keys的宽松类型定义:
function objectKeys<T extends object>(obj: T) { return Object.keys(obj) as Array<keyof T>; }
再修改组件代码,替换原有Object.keys调用,补充必要的类型收窄即可:
export const LightTheme = () => ( <div> {objectKeys(light_theme.colors).map((type) => { const currentColorGroup = light_theme.colors[type]; return ( <TypeContainer key={type}> <TypeTitle>{startCase(type)}</TypeTitle> <ColorTable> <thead> <tr> <NameTh>Name</NameTh> <ValueTh>Value</ValueTh> </tr> </thead> <tbody> {objectKeys(currentColorGroup).map((color_name) => ( <ColorRow key={color_name as string}> <CodeTd> <Code> theme.{type}.{color_name as string} </Code> </CodeTd> <td> <ColorDemoContainer> <ColorBox color={currentColorGroup[color_name as keyof typeof currentColorGroup]} /> <ColorValue> {currentColorGroup[color_name as keyof typeof currentColorGroup]} </ColorValue> </ColorDemoContainer> </td> </ColorRow> ))} </tbody> </ColorTable> <Divider /> </TypeContainer> ) })} </div> );
方案2:显式定义主题类型(适合宽松校验场景)
如果不需要严格的字面量类型校验,可以提前给主题对象定义宽松的接口类型,让TypeScript直接确认所有层级的属性索引返回的都是颜色字符串,不需要额外的单次断言:
// 定义宽松的主题接口类型 interface ITheme { colors: { [groupKey: string]: { [colorKey: string]: string; } } } // 给light_theme指定类型,原有对象内容不变 export const light_theme: ITheme = Object.freeze({ colors: { brand: { primary: COLORS.ROSE_500, secondary: COLORS.BLACK_50, background: COLORS.WHITE, }, button: { action: COLORS.RED_500, action_hover: COLORS.RED_600, interactive: COLORS.OCEAN_500, interactive_hover: COLORS.DARK_OCEAN, neutral: COLORS.WHITE, disabled: COLORS.GREY_300, }, } });
使用该方案后,你原有组件代码仅需删除light_theme.colors[type as keyof typeof light_theme.colors]中的类型断言即可正常运行,不会再报类型错误。
内容的提问来源于stack exchange,提问作者bigpotato
相关产品推荐
相关产品推荐

