如何用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
相关产品推荐
相关产品推荐

