TypeScript 索引接口值为枚举/枚举Record时报隐式any类型错误
TypeScript 联合类型索引报错修正方案
报错核心原因
- 缺少类型收窄逻辑:原
ErrorByCode定义的属性值是ERRORS | Record<ErrorType, ERRORS>的联合类型,未做类型判断就直接用type做索引时,TypeScript无法确定当前值是可索引的嵌套映射对象,还是无对应属性的字符串枚举值,因此触发“在ERRORS类型上不存在'blue'属性”的报错。 - 原代码隐含两处问题:
- 入参类型标注错误:
errorResolver的入参type被写为ERRORS枚举类型,与实际传入的'blue'类字面量值不匹配 - 短路逻辑顺序错误:原写法
(ERRORS_BY_CODE?.[code] || ERRORS_BY_CODE?.[code]?.[type])中,只要ERRORS_BY_CODE[code]是合法枚举值,就会直接命中短路返回,嵌套取值分支永远不会触发,不符合预期逻辑。
- 入参类型标注错误:
修正实现
不需要修改原有类型定义,只需要在访问嵌套属性前补充类型判断、收窄联合类型,同时修正错误的类型标注和逻辑顺序即可:
- 单独取出code对应的属性值,通过
typeof判断当前值是否为对象结构:因为字符串枚举的本质是字符串,判断结果为'string',嵌套映射对象的判断结果为'object',两者可精准区分 - 分支判断后,在对象分支中用
type取值,在枚举分支中直接返回枚举值 - 调整兜底逻辑,修正原代码中拼写错误的
ERRORS_COMPONENTS_BY_CODE为ERRORS_BY_CODE
修正后可正常编译运行的代码
export enum ERRORS { ERROR1 = 'Error1', ERROR2 = 'Error2', } export type ErrorType = 'blue' | 'green'; export interface ErrorByCode { [key: string]: ERRORS | Record<ErrorType, ERRORS>; } const ERRORS_BY_CODE: ErrorByCode = { default: ERRORS.ERROR1, '01': ERRORS.ERROR2, '2': { blue: ERRORS.ERROR1, green: ERRORS.ERROR2, }, }; const errorResolver = ({code, type}: {code: string; type: ErrorType}) => { const codeValue = ERRORS_BY_CODE[code]; let errorMessage: ERRORS; // 类型收窄:仅在值为嵌套映射对象时执行属性访问 if (codeValue && typeof codeValue === 'object') { errorMessage = codeValue[type]; } else { errorMessage = codeValue; } // 兜底返回默认错误值 return errorMessage ?? ERRORS_BY_CODE.default as ERRORS; }; // 正常调用测试 console.log(errorResolver({code: '01', type: 'blue'})) // 输出 Error2 console.log(errorResolver({code: '2', type: 'green'})) // 输出 Error2
方案有效性说明
加入typeof codeValue === 'object'的判断后,TypeScript会自动将当前分支的codeValue类型从联合类型中收窄为Record<ErrorType, ERRORS>,此时用type(即ErrorType字面量联合类型)做索引完全符合类型规则,不会再尝试在ERRORS枚举值上访问不存在的属性。
内容的提问来源于stack exchange,提问作者Palaniichuk Dmytro
相关产品推荐
相关产品推荐

