TypeScript中使用forEach()解析嵌套接口的id与targets数据
问题背景
CountTargetsData 是用于JSON数据解析的类型约束接口,对应的数据存在多层嵌套,定义代码如下:
interface CountTargetsData { data: { [state: string]: { [date: string]: { [index: string]: { [id: string]: { [targets: string]: number } }, }, }, }; } const parseCounters = useCallback( async (responseDeploymentData: CountTargetsData) => { // 在此处解析id和targets字段 } );
需求是针对上述多层嵌套结构,仅使用forEach()方法访问每条数据中的id与targets字段,参考示例数据如下:
{ "data": { "stateA": { "2016-06-03": [ { "1200": { "count_targets": 1, "count_targets_excluded": 0, "count_targets_pending": 0, "count_targets_in_progress": 0, "count_targets_completed": 0, "count_targets_failed": 1 } } ], "2016-06-07": [ { "1455": { "count_targets": 1, "count_targets_excluded": 0, "count_targets_pending": 0, "count_targets_in_progress": 0, "count_targets_completed": 1, "count_targets_failed": 0 } } ] } } }
注:示例数据中date层级对应的值为数组结构,和初始接口定义的纯对象结构存在差异,实现时需要做兼容处理。
实现方案
JS/TS中只有数组原型挂载了forEach方法,对象类型的嵌套层需要先通过Object.keys()/Object.values()取出键/值集合转成数组,再逐层调用forEach遍历即可,完整实现代码如下:
const parseCounters = useCallback( async (responseDeploymentData: CountTargetsData) => { // 存储解析结果,可根据业务需求调整结构 const parsedResult: Array<{ state: string; date: string; id: string; targets: Record<string, number>; }> = []; // 第一层:遍历最外层data下的所有state维度数据 Object.keys(responseDeploymentData.data).forEach((stateKey) => { const stateVal = responseDeploymentData.data[stateKey]; // 第二层:遍历当前state下的所有date维度数据 Object.keys(stateVal).forEach((dateKey) => { const dateVal = stateVal[dateKey]; // 兼容示例数据中date层为数组的情况,统一转成数组处理 const indexGroup = Array.isArray(dateVal) ? dateVal : Object.values(dateVal); // 第三层:遍历当前日期下的所有索引分组 indexGroup.forEach((indexItem) => { // 第四层:遍历分组内的所有id Object.keys(indexItem).forEach((idKey) => { // 到这一层已经拿到需要的id和对应targets对象 const targetsVal = indexItem[idKey]; // 按业务需求处理即可,示例是存入结果数组 parsedResult.push({ state: stateKey, date: dateKey, id: idKey, targets: targetsVal }); // 如果需要访问targets内部的具体统计字段,再加一层forEach遍历即可 Object.keys(targetsVal).forEach((targetField) => { const fieldValue = targetsVal[targetField]; // 例如读取count_targets、count_targets_failed等字段的值做后续计算 console.log(`${stateKey}-${dateKey}-${idKey} 字段${targetField}值为${fieldValue}`); }) }) }) }) }) return parsedResult; } );
注意事项
- 不要直接对普通对象调用
forEach,会报方法不存在的错误,必须先通过Object.keys/Object.values转成数组再调用 - 如果实际数据结构和接口定义有出入(比如示例里date层为数组的情况),遍历前先做类型判断兼容,避免运行时报错
- 遍历过程中可以根据业务需求跳过不需要的分支,不用强制走完所有嵌套层级
内容的提问来源于stack exchange,提问作者user19251203
相关产品推荐
相关产品推荐

