如何合并功能相似的TypeScript数据处理方法以避免重复代码?
合并相似TypeScript数据处理方法的解决方案
问题背景
现有两个功能高度相似的TypeScript方法,用于处理Customer数组并生成不同图表组件所需的数据:
processCategoryData:处理分类数据,输出ChartDataCategory[]类型,结构为{ value: string, count: number }processDateData:处理日期数据,输出ChartDataDate[]类型,结构为{ date: number, value: number }
两者核心逻辑完全一致,仅字段名称和类型存在差异,希望合并为单一方法以消除代码重复。
原方法代码:
private processCategoryData( data: Customer[], keySelector: (item: Customer) => string ): ChartDataCategory[] { const result: ChartDataCategory[] = []; data.forEach((item) => { const keyValue = keySelector(item); const existingItem = result.find((obj) => obj.value === keyValue); if (existingItem) { existingItem.count += 1; } else { result.push({ value: keyValue, count: 1 }); } }); return result; } private processDateData( data: Customer[], keySelector: (item: Customer) => number ): ChartDataDate[] { const result: ChartDataDate[] = []; data.forEach((item) => { const keyValue = keySelector(item); const existingItem = result.find((obj) => obj.date === keyValue); if (existingItem) { existingItem.value += 1; } else { result.push({ date: keyValue, value: 1 }); } }); return result; }
解决方案
通过泛型+配置参数的方式,将方法的可变部分(字段名称、类型)抽离为可配置项,复用核心计数逻辑:
1. 合并后的通用方法
// 保留原有类型定义 type ChartDataCategory = { value: string, count: number }; type ChartDataDate = { date: number, value: number }; // 假设你的Customer类型定义如下(根据实际情况调整) type Customer = { /* 你的Customer字段 */ }; private processChartData<T extends Record<string, any>>( data: Customer[], keySelector: (item: Customer) => T[keyof T], config: { keyField: keyof T, countField: keyof T } ): T[] { const result: T[] = []; data.forEach((item) => { const keyValue = keySelector(item); // 根据配置的keyField查找已有项 const existingItem = result.find(obj => obj[config.keyField] === keyValue); if (existingItem) { // 根据配置的countField累加计数 existingItem[config.countField] += 1; } else { // 创建新项并指定字段 const newItem = { [config.keyField]: keyValue, [config.countField]: 1 } as T; result.push(newItem); } }); return result; }
2. 调用示例
处理分类数据
const categoryChartData = this.processChartData<ChartDataCategory>( customerList, (customer) => customer.category, // 假设Customer有string类型的category字段 { keyField: 'value', countField: 'count' } );
处理日期数据
const dateChartData = this.processChartData<ChartDataDate>( customerList, (customer) => customer.registerTimestamp, // 假设Customer有number类型的registerTimestamp字段 { keyField: 'date', countField: 'value' } );
方案说明
- 泛型T:用于约束输出数据的类型,确保返回值与目标图表数据结构匹配
- config参数:指定输出对象中的「键字段」(用于分组的字段)和「计数字段」(用于累加的字段),将两个方法的差异转化为配置
- 类型安全:通过
keyof T确保配置的字段名属于目标类型T的属性,避免拼写错误
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

