TypeScript中使用枚举作为键提取值并转换枚举类型报错求助
问题
我在尝试以枚举类型作为键从对象中提取值,并将其转换为该枚举类型时遇到了大量错误。提取类型后,我将其传入函数以根据该类型进一步处理数据。代码示例如下:
export enum TestElement { Type = 'T', Serial = 'S', } const data = '{"TEST1":{"T":"XX2","S":8374373}}'; const parsed: object = JSON.parse(data); // Get the first element const extracted: object = Object.values(parsed)[0]; // Get the type const type: TestElement = extracted[TestElement.Type]; handler(type, extracted)();
在const type: TestElement = extracted[TestElement.Type]处出现错误:
Element implicitly has an 'any' type because expression of type 'TestElement.Type' can't be used to index type '{}'. Property '[TestElement.Type]' does not exist on type '{}'.ts(7053)
另外一段代码:
const handler = ( type: TestElement, data: object, ): (() => void) => processTypes[type] ? () => processTypes[type](data[type]()) : () => { throw new Error( 'Type not supported or unknown', ); };
在processTypes[type](data[type]())处出现错误:
Element implicitly has an 'any' type because expression of type 'TestElement' can't be used to index type '{}'. Property '[TestElement.Type]' does not exist on type '{}'.ts(7053)
还有processTypes的定义:
const processTypes: { [key: string]: (data: {[key in TestElement]: string}) => void; } = { XX1: data => { console.log({data}); }, XX2: data => { console.log({data}); }, };
请问我哪里出错了?是否有正确的实现方式?
问题分析
核心问题是你给parsed和extracted都标注了object类型,TypeScript中object是最宽泛的顶层类型,不包含任何具体属性信息,导致TS无法确认extracted上存在TestElement.Type对应的键,进而抛出索引错误。
此外还有几个细节问题:
data[type]()是错误写法,data[type]是属性值而非函数,不需要加调用符号()processTypes的键是XX1、XX2这类业务标识字符串,但你用TestElement枚举类型的值去索引它,类型不匹配processTypes的参数类型定义中,Serial对应的JSON值是数字,但你定义成了string,类型不兼容
修正后的实现
通过定义明确的类型接口,给JSON解析结果指定精准类型,逐步修正所有类型匹配问题:
export enum TestElement { Type = 'T', Serial = 'S', } // 定义单个数据项的结构类型,匹配JSON中的实际值类型 interface ItemData { [TestElement.Type]: 'XX1' | 'XX2'; [TestElement.Serial]: number; } // 定义解析后的整体数据结构 interface ParsedData { [key: string]: ItemData; } const dataStr = '{"TEST1":{"T":"XX2","S":8374373}}'; // 给JSON.parse添加类型断言,明确解析后的结构类型 const parsed = JSON.parse(dataStr) as ParsedData; // 提取第一个元素,此时extracted自动推导为ItemData类型 const extracted = Object.values(parsed)[0]; // 提取类型标识,自动推导为'XX1'|'XX2' const type = extracted[TestElement.Type]; // 重新定义processTypes,键类型与type严格匹配,参数类型匹配ItemData const processTypes: { [K in typeof type]: (data: ItemData) => void; } = { XX1: data => { console.log('处理XX1类型数据:', data); }, XX2: data => { console.log('处理XX2类型数据:', data); }, }; // 修正handler的类型定义,确保参数和逻辑匹配 const handler = ( type: typeof type, data: ItemData, ): (() => void) => { const processor = processTypes[type]; return processor ? () => processor(data) : () => { throw new Error('不支持的类型或未知类型'); }; }; // 调用测试 handler(type, extracted)();
关键修正点说明
- 用明确的接口类型替代宽泛的
object,让TS能识别对象的属性结构 - 移除
data[type]()中多余的(),修正语法错误 - 让
processTypes的键类型和extracted[TestElement.Type]的类型严格对齐,消除类型不兼容问题 - 调整参数类型,确保
Serial的数字类型与JSON中的实际值一致
内容的提问来源于stack exchange,提问作者Nkk
相关产品推荐
相关产品推荐

