TypeScript中如何将对象内的数组转换为对象结构
解决TypeScript中JSON数组转日期键对象的类型错误问题
为了缩减大体积JSON文件的大小,我把原本每个对象中重复的日期字段改成用values数组存储对应值,但在TypeScript里转成日期作为键的对象结构时遇到了问题。
输入数据
const rows = [ { 'name': '100100', 'description': 'Dummy 00', 'hierarchy': ['Final_Hierarchy'], 'id': 0, 'values': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], } ]; const columns = [ '2022-09-18', '2022-09-25', '2022-10-02', '2022-10-09', '2022-10-16', '2022-10-23', '2022-10-30', '2022-11-06', '2022-11-13', '2022-11-20', '2022-11-27', '2022-12-04', ];
期望输出
const rows = [ { 'name': '100100', 'description': 'Dummy 00', 'hierarchy': ['Final_Hierarchy'], 'id': 0, '2022-09-18': 0, '2022-09-25': 0, '2022-10-02': 0, '2022-10-09': 0, '2022-10-16': 0, '2022-10-23': 0, '2022-10-30': 0, '2022-11-06': 0, '2022-11-13': 0, '2022-11-20': 0, '2022-11-27': 0, '2022-12-04': 0, }, ];
尝试的代码及错误
我试过下面的代码,但报出错误:No index signature with a parameter of type 'string' was found on type '{}'
var result = {}; columns.forEach((key, i) => result[key] = rows.values[i]);
解决方案
错误原因
rows是数组,不能直接访问rows.values,需要取数组中的单个元素(比如rows[0].values);- TypeScript默认不对空对象
{}添加索引签名,因此无法直接用字符串作为键赋值,需要明确指定类型。
方法1:添加索引签名类型
直接给结果对象定义索引签名,同时修正数组访问的问题,并合并原对象的其他属性:
// 转换多条数据的写法 const transformedRows = rows.map(row => { const dateValues: {[key: string]: number} = {}; columns.forEach((key, i) => { dateValues[key] = row.values[i]; }); const {values, ...rest} = row; return {...rest, ...dateValues}; });
方法2:使用类型断言
通过类型断言告诉TypeScript空对象可以接受字符串键:
const transformedRows = rows.map(row => { const dateValues = columns.reduce((acc, key, idx) => { acc[key] = row.values[idx]; return acc; }, {} as {[key: string]: number}); const {values, ...rest} = row; return {...rest, ...dateValues}; });
方法3:定义严谨的接口
如果需要更规范的类型约束,可以预先定义接口:
// 原始数据结构接口 interface OriginalRow { name: string; description: string; hierarchy: string[]; id: number; values: number[]; } // 转换后的数据结构接口 interface TransformedRow extends Omit<OriginalRow, 'values'> { [key: string]: string | number | string[]; } const transformedRows: TransformedRow[] = rows.map(row => { const dateObj = columns.reduce((acc, col, i) => { acc[col] = row.values[i]; return acc; }, {} as Record<string, number>); const {values, ...rest} = row; return {...rest, ...dateObj} as TransformedRow; });
内容的提问来源于stack exchange,提问作者moritzr92
相关产品推荐
相关产品推荐

