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

如何用TypeScript为数据集扁平化函数定义泛型签名

问题描述

给定如下结构的数据集:

const dataset = [
  { date: "2022-01-01", category: "red", value: 10 },
  { date: "2022-01-01", category: "blue", value: 20 },
  { date: "2022-01-01", category: "gold", value: 30 },
  { date: "2022-01-01", category: "green", value: 40 },
  { date: "2022-01-02", category: "red", value: 5 },
  { date: "2022-01-02", category: "blue", value: 15 },
  { date: "2022-01-02", category: "gold", value: 25 },
  { date: "2022-01-02", category: "green", value: 35 }
];

需要将其扁平化为按**主属性(如date)分组,把分类属性(如category)**转为对象键、**值属性(如value)**作为对应值的格式:

const flattenDataset = [
  { "date": "2022-01-01", "red": 10, "blue": 20, "gold": 30, "green": 40 },
  { "date": "2022-01-02", "red": 5, "blue": 15, "gold": 25, "green": 35 }
];

已实现功能函数flatDataset,但参数dataset类型为any,需要通过TypeScript为该函数定义泛型签名,约束输入数据集必须包含指定的主属性、分类属性、值属性,同时要适配其他属性名的数据集(比如主属性为apple、分类属性为color、值属性为something的场景)。

TypeScript泛型实现方案

我们可以通过多泛型参数来约束函数的输入和输出类型,同时让TypeScript自动推断属性对应的类型:

type FlattenedItem<
  MainProp extends string,
  Category extends string | number | symbol,
  Value,
  MainValue
> = {
  [K in MainProp]: MainValue;
} & {
  [K in Category]: Value;
};

function flatDataset<
  MainProp extends string,
  CategoryProp extends string,
  ValueProp extends string,
  Item extends Record<MainProp, any> & Record<CategoryProp, string | number | symbol> & Record<ValueProp, any>
>(
  dataset: Item[],
  mainProperty: MainProp,
  categoryProperty: CategoryProp,
  valueProperty: ValueProp
): FlattenedItem<MainProp, Item[CategoryProp], Item[ValueProp], Item[MainProp]>[] {
  // 函数核心实现逻辑
  const resultMap = new Map<Item[MainProp], Partial<FlattenedItem<MainProp, Item[CategoryProp], Item[ValueProp], Item[MainProp]>>>();

  for (const item of dataset) {
    const mainValue = item[mainProperty];
    const categoryValue = item[categoryProperty];
    const value = item[valueProperty];

    if (!resultMap.has(mainValue)) {
      resultMap.set(mainValue, { [mainProperty]: mainValue } as any);
    }

    const currentItem = resultMap.get(mainValue)!;
    currentItem[categoryValue as keyof typeof currentItem] = value;
  }

  return Array.from(resultMap.values()) as FlattenedItem<MainProp, Item[CategoryProp], Item[ValueProp], Item[MainProp]>[];
}

泛型参数说明

  • MainProp: 指定主属性的名称(如"date"),约束为字符串类型。
  • CategoryProp: 指定分类属性的名称(如"category"),约束为字符串类型。
  • ValueProp: 指定值属性的名称(如"value"),约束为字符串类型。
  • Item: 输入数据集中单个元素的类型,通过Record约束它必须包含上述三个属性。

使用示例

调用函数时,TypeScript会自动推断所有类型:

// 自动推断返回类型为:Array<{ date: string; red: number; blue: number; gold: number; green: number }>
const flattened = flatDataset(dataset, "date", "category", "value");

适配其他场景示例

如果有另一个数据集:

const fruitDataset = [
  { apple: "red", color: "dark", something: 100 },
  { apple: "red", color: "light", something: 200 },
  { apple: "green", color: "dark", something: 150 },
  { apple: "green", color: "light", something: 250 }
];

调用函数时同样能获得准确的类型推断:

// 返回类型为:Array<{ apple: string; dark: number; light: number }>
const flattenedFruits = flatDataset(fruitDataset, "apple", "color", "something");

内容的提问来源于stack exchange,提问作者marielle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:05:21