typescript - 通用接口中的通用原型函数?大批。通过...分组(道具):{键:K,数组:T[]}[]
问题描述
所以我试图使这项工作:Array<T>.groupBy<KeyType> (property): {key: KeyType, array: Array<T> }[];
代码如下所示:
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) {
Array.prototype.groupBy = function <KeyType = string>(
property: ArrayByParameter<any, KeyType>
) {
let callbackFunction: (item: any) => any;
if (typeof property === "string") {
callbackFunction = (mapObj) => mapObj[property];
} else if (typeof property === "function") {
callbackFunction = property;
} else {
throw "Parameter is not a string nor a function!";
}
// Edit version of : https://stackoverflow.com/a/34890276/3781156
return Object.entries(
this.reduce(function (rv, x) {
(rv[callbackFunction(x)] = rv[callbackFunction(x)] || []).push(
x
);
return rv;
}, {}) as { [key: string]: Array<any> }
).map(([key, array]) => {
return { key, array };
});
};
}
type Characters = "A" | "B" | "C";
type Numbers = "1" | "2" | "3";
type SomeKeyType = `${Characters}-${Numbers}`;
// Same thing as below.
type SomeKeyType2 =
| "A-1"
| "A-2"
| "A-3"
| "B-1"
| "B-2"
| "B-3"
| "C-1"
| "C-2"
| "C-3";
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 },
// ...
];
const groupByArray: { key: SomeKeyType; array: SomeObject[] }[] =
array.groupBy<KeyType>((obj: SomeObject) => `${obj.c}-${obj.n}`);
Result expected :
[
{key: "A-1", array: [{c:A, n:1, /*...*/}]},
{key:"A-2", array: [{/*...*/},{/*...*/}]},
{key:"B-1", array:[{/*...*/}]},
/*...*/
];
我在“Array.prototype.groupBy”的第 12 行遇到这样的错误:
类型 '<KeyType = string>(property: ArrayByParameter<any, KeyType>) => { key: string; 数组:任何[];}[]' 不可分配给类型 '<KeyType = string>(property: ArrayByParameter<any, KeyType>) => { key: KeyType; 数组:任何[];}[]'。键入'{键:字符串;数组:任何[];}[]' 不可分配给类型 '{ key: KeyType; 数组:任何[];}[]'。键入'{键:字符串;数组:任何[];}' 不可分配给类型 '{ key: KeyType; 数组:任何[];}'。属性“键”的类型不兼容。类型“字符串”不可分配给类型“KeyType”。'KeyType' 可以用与 'string'.ts(2322) 无关的任意类型实例化
我认为我的 KeyType 定义是问题所在,但我无法找到解决方案。KeyType 是一个字符串,但也可以是我现在想要的模板文字类型。
所以 :
- 我怎样才能解决这个问题,使代码工作?
- 有没有办法在 Array.prototype.groupBy 函数中获取 T 泛型?
- 现在,T 被替换为 any,因为我不知道如何在原型定义中使用 T。
提前致谢 !:)
解决方案
我该如何解决这个问题以便KeyType
匹配?
这里的关键问题Object.entries
是当前将key
索引器硬编码为string
而不是允许K extends PropertyKey
(PropertyKey
是可以在 JavaScript 中索引到对象中的所有类型的内置类型别名)。
没有什么是我们无法通过额外的环境类型定义来解决的:
declare module "our-global-ambient-module" {
global {
interface Array<T> {
groupBy<KeyType extends PropertyKey = string>(
property: ArrayByParameter<T, KeyType>
): { key: KeyType; array: T[] }[];
}
// What we've added - an overload to `Object.entries`
// that will preserve the key's type.
interface ObjectConstructor {
entries<K extends PropertyKey, V>(object: any): [K, V][];
}
}
}
操场上的完整代码在这里
有没有办法在函数中获得T
泛型Array.prototype.groupBy
是的,只需添加一个类型参数和类型this
为该类型:
Array.prototype.groupBy = function <T, KeyType extends PropertyKey = string>(
this: T[],
property: ArrayByParameter<any, KeyType>
)
您还需要{}
在reduce
通话中注释类型:
{} as {[X in KeyType]: T[]}
推荐阅读
- matlab - 检查每个矩阵元素是否不同
- macos - 如何修复 brew 安装的 MariaDB 挂在“mysql.server stop”上并且不会停止?
- ruby-on-rails - “未初始化的常量 Api::V1::ReservationOptionsController::ReservationOptions”
- javascript - DataTable 显示零数据消息,即使出现数据 (Angular)
- python - 如何在新数据上使用决策树回归器?(Python、熊猫、Sklearn)
- javascript - Vue 父子发出函数正在破坏 v-model 绑定
- sql - 从 SQL 列中取出 %
- java - 如果数字存在,则在具有排序列的矩阵中搜索
- android - 带有 Recycler View 和 AppBar 的嵌套滚动
- plot - 3D 矢量场