如何在TypeScript中为groupBy函数声明基于参数的动态返回类型
为动态分组函数添加TypeScript类型定义
要让这个groupBy函数支持任意数组的动态分组,同时保留完整的类型提示,可以用TypeScript泛型+索引类型实现,下面是具体改造方案:
完整类型化后的代码
const cars = [ { 'make': 'audi', 'model': 'r8', 'year': '2012' }, { 'make': 'audi', 'model': 'rs5', 'year': '2013' }, { 'make': 'ford', 'model': 'mustang', 'year': '2012' }, { 'make': 'ford', 'model': 'fusion', 'year': '2015' }, { 'make': 'kia', 'model': 'optima', 'year': '2012' }, ]; // 泛型定义让函数适配任意对象数组和分组键 export function groupBy<Item extends Record<string, unknown>, Key extends keyof Item>( key: Key, items: Item[], itemsName: string ): Array<{ [K in Key]: Item[K] } & Record<string, Item[]>> { // 创建分组对象 const groupsObj = items.reduce((acc, curr) => { const property = curr[key]; // 断言分组键为合法对象键类型 const propKey = property as string | number | symbol; if (propKey in acc) { return { ...acc, [propKey]: [...acc[propKey], curr] }; } return { ...acc, [propKey]: [curr] }; }, {} as Record<string | number | symbol, Item[]>); // 转换为最终数组结构,保留原属性类型 const groupsArr = Object.keys(groupsObj).map((property) => ({ [key]: groupsObj[property][0][key], [itemsName]: groupsObj[property], })) as Array<{ [K in Key]: Item[K] } & Record<string, Item[]>>; return groupsArr; } // 调用示例:自动获得类型提示 const groupedCars = groupBy('year', cars, 'cars'); // groupedCars类型会被推断为:Array<{ year: string; cars: typeof cars[0][] }>
关键类型说明
泛型参数约束
Item extends Record<string, unknown>:限制输入数组的元素为任意对象类型Key extends keyof Item:确保传入的分组键key是数组元素对象上存在的属性
返回值类型
Array<{ [K in Key]: Item[K] } & Record<string, Item[]>>:明确返回数组的每个元素,既包含分组键对应的属性(类型与原对象一致),又包含以itemsName为键、对应分组数组的属性
类型断言处理
- 初始化
reduce的累加器时,用as Record<string | number | symbol, Item[]>明确分组对象的类型 - 转换数组时直接取分组内第一个元素的
key值,避免原属性类型(如数字)被强制转为字符串
- 初始化
其他场景适配示例
比如用它分组餐馆预约数组:
interface RestaurantBooking { date: string; name: string; guests: number; } const bookings: RestaurantBooking[] = [ { date: '2024-05-20', name: 'Little Italy', guests: 4 }, { date: '2024-05-20', name: 'Sushi Bar', guests: 2 }, { date: '2024-05-21', name: 'Burger Joint', guests: 3 }, ]; const groupedBookings = groupBy('date', bookings, 'bookings'); // groupedBookings类型自动推断为:Array<{ date: string; bookings: RestaurantBooking[] }>
内容的提问来源于stack exchange,提问作者Alamin Shaikh
相关产品推荐
相关产品推荐

