如何为Array原型正确扩展groupBy方法(含已有distinct实现)
如何将groupBy函数扩展为Array的原型方法
我已经实现了一个groupBy函数,现在想把它扩展成Array的原型方法,让数组可以直接调用myItems.groupBy(item => item.key)。目前已经有了Array的distinct扩展代码,请问怎么正确完成groupBy的扩展?
现有groupBy函数代码:
const groupBy = <T>(array: T[], predicate: (value: T, index: number, array: T[]) => string) => array.reduce((acc, value, index, array) => { (acc[predicate(value, index, array)] ||= []).push(value); return acc; }, {} as { [key: string]: T[] });
已有Array扩展代码:
export { }; declare global { interface Array<T> { distinct(): Array<T>; } } if (!Array.prototype.distinct) { Array.prototype.distinct = function <T>(): T[] { const stringifiedItems = this.map((item) => JSON.stringify(item)); const set = new Set(stringifiedItems); return Array.from(set).map((item) => JSON.parse(item)); }; }
实现步骤
1. 扩展Array的全局类型声明
在全局Array<T>接口中添加groupBy方法的类型定义,和原函数的参数、返回值类型保持一致:
export { }; declare global { interface Array<T> { distinct(): Array<T>; // 添加groupBy的类型声明 groupBy(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] }; } }
2. 实现groupBy原型方法
参照distinct的实现逻辑,先检查方法是否已存在(避免覆盖原生或第三方库的同名方法),再把原groupBy的逻辑迁移到原型方法中——这里的this就是当前调用的数组实例:
if (!Array.prototype.groupBy) { Array.prototype.groupBy = function <T>(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] } { return this.reduce((acc, value, index, array) => { const key = predicate(value, index, array); (acc[key] ||= []).push(value); return acc; }, {} as { [key: string]: T[] }); }; }
完整整合代码
将两部分合并后的完整代码如下:
export { }; declare global { interface Array<T> { distinct(): Array<T>; groupBy(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] }; } } // 实现distinct方法 if (!Array.prototype.distinct) { Array.prototype.distinct = function <T>(): T[] { const stringifiedItems = this.map((item) => JSON.stringify(item)); const set = new Set(stringifiedItems); return Array.from(set).map((item) => JSON.parse(item)); }; } // 实现groupBy方法 if (!Array.prototype.groupBy) { Array.prototype.groupBy = function <T>(predicate: (value: T, index: number, array: T[]) => string): { [key: string]: T[] } { return this.reduce((acc, value, index, array) => { const key = predicate(value, index, array); (acc[key] ||= []).push(value); return acc; }, {} as { [key: string]: T[] }); }; }
使用示例
现在可以按预期调用方法:
const myItems = [ { key: 'a', value: 1 }, { key: 'b', value: 2 }, { key: 'a', value: 3 } ]; const grouped = myItems.groupBy(item => item.key); // 输出:{ a: [{ key: 'a', value: 1 }, { key: 'a', value: 3 }], b: [{ key: 'b', value: 2 }] }
注意事项
- 用
if (!Array.prototype.groupBy)做存在性检查,防止意外覆盖已有方法 - 保持泛型
T和Array的泛型一致,保证类型安全 - 原函数中的
array参数对应原型方法里的this,迁移时注意替换
内容的提问来源于stack exchange,提问作者pianoman102
相关产品推荐
相关产品推荐

