You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并功能相似的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:20:33