// 定义一个接口，键为字符串，值为任意类型
interface StringKeyObject {
  [key: string]: any;
}

interface ResultObject<T> {
  [key: string]: T;
}

type GroupFunction<T> = (item: T) => string;

/**
 * 分组函数
 * @param {Array} arr
 * @param {string|GroupFunction} generatekey
 * @returns {object}
 */
export function group<T extends StringKeyObject>(
  arr: T[],
  generatekey: string | GroupFunction<T>
): ResultObject<T[]> {
  if (typeof generatekey === "string") {
    const proName = generatekey;
    generatekey = (item: T) => item[proName];
  }
  return arr.reduce((result: ResultObject<T[]>, currentValue: T) => {
    const key = generatekey(currentValue);
    (result[key] = result[key] || []).push(currentValue);
    return result;
  }, {});
}

// 使用示例
let arr = [
  { name: "张三", age: 18 },
  { name: "张三", age: 18 },
  { name: "张三", age: 19 },
  { name: "李四", age: 18 },
  { name: "李四", age: 18 },
  { name: "李四", age: 19 },
];

type Person = {
  name: string;
  age: number;
};
const arr2 = group<Person>(arr, "name");
console.log(arr2);
const arr3 = group<Person>(arr, (item) => item.age.toString());
console.log(arr3);
