// 重载1: 按对象属性分组
function groupBy<T, K extends keyof T>(
  array: T[],
  key: K
): T[K] extends keyof any ? Record<T[K] & keyof any, T[]> : never;

// 重载2: 按函数返回值分组
function groupBy<T, K extends keyof any>(
  array: T[],
  fn: (item: T) => K
): Record<K, T[]>;

// 实现
function groupBy<T, K extends keyof any>(
  array: T[],
  keyOrFn: K | ((item: T) => K)
): Record<K, T[]> {
  return array.reduce((result, item) => {
    // 确定分组键
    const key =
      typeof keyOrFn === "function" ? keyOrFn(item) : (item as any)[keyOrFn];

    // 如果该分组不存在，则初始化一个空数组
    if (!result[key]) {
      result[key] = [];
    }

    // 将当前项添加到对应的分组中
    result[key].push(item);

    return result;
  }, {} as Record<K, T[]>);
}

// 示例用法
// 1. 定义一个接口用于测试
interface Person {
  name: string;
  age: number;
  gender: "male" | "female";
  department: string;
}

// 2. 创建测试数据
const people: Person[] = [
  { name: "Alice", age: 25, gender: "female", department: "engineering" },
  { name: "Bob", age: 30, gender: "male", department: "marketing" },
  { name: "Charlie", age: 35, gender: "male", department: "engineering" },
  { name: "Diana", age: 28, gender: "female", department: "marketing" },
  { name: "Eve", age: 40, gender: "female", department: "engineering" },
];

// 3. 按属性分组 - 按部门分组
const groupedByDepartment = groupBy(people, "department");
console.log("按部门分组:", groupedByDepartment);

// 4. 按函数结果分组 - 按年龄段分组
const groupedByAgeRange = groupBy(people, (person) => {
  if (person.age < 30) return "young";
  if (person.age < 40) return "middle";
  return "senior";
});
console.log("按年龄段分组:", groupedByAgeRange);

// 5. 按性别分组
const groupedByGender = groupBy(people, "gender");
console.log("按性别分组:", groupedByGender);
