TypeScript 为泛型Array<T>接口添加groupBy原型方法报错求助
问题解决方案
1. 报错修复方案
报错的根本原因:Object.entries方法返回的键类型固定为string,和你定义的泛型KeyType不匹配,TS无法自动推导你返回的key确实符合传入的KeyType类型,需要你手动添加安全的类型断言。
调整后的完整可运行代码如下:
type ArrayByParameter<T, KeyType = any> = string | ((item: T) => KeyType); declare global { interface Array<T> { groupBy<KeyType = string>( property: ArrayByParameter<T,KeyType> ): { key: KeyType; array: T[] }[]; } } if (!Array.prototype.groupBy) { // 给this指定类型为T[],即可直接拿到数组的元素泛型T,无需使用any Array.prototype.groupBy = function <T, KeyType = string>( this: T[], property: ArrayByParameter<T, KeyType> ) { let callbackFunction: (item: T) => KeyType; if (typeof property === "string") { callbackFunction = (mapObj) => mapObj[property as keyof T] as KeyType; } else if (typeof property === "function") { callbackFunction = property; } else { throw "Parameter is not a string nor a function!"; } const groupMap = this.reduce(function (rv, x) { const key = callbackFunction(x); (rv[key] = rv[key] || []).push(x); return rv; }, {} as Record<KeyType, T[]>); return Object.entries(groupMap).map(([key, array]) => { // 逻辑上所有key都是回调返回的KeyType类型,此处断言安全 return { key: key as KeyType, array }; }); }; } // 测试用例 type Characters = "A" | "B" | "C"; type Numbers = "1" | "2" | "3"; type SomeKeyType = `${Characters}-${Numbers}`; type SomeObject = { c: Characters; n: Numbers; }; const array: SomeObject[] = [ { c: "A", n: "1" }, { c: "A", n: "2" }, { c: "A", n: "2" }, { c: "B", n: "1" }, ]; // 调用时传入对应KeyType泛型即可 const groupByArray = array.groupBy<SomeKeyType>((obj) => `${obj.c}-${obj.n}`);
2. 关于Array原型方法获取泛型T的说明
可以直接获取,TS提供了专门的语法支持:在定义原型方法时,在函数的第一个参数位置显式声明this的类型为T[]即可。这个this参数仅用于类型推导,不会占用实际运行时的参数位置,调整后你就可以在整个方法里使用数组的元素泛型T,完全不需要用any替代。
内容的提问来源于stack exchange,提问作者Maxime4000
相关产品推荐
相关产品推荐

