简体   繁体   English

T[keyof T] 不能用于索引 {}

[英]T[keyof T] cannot be used to index {}

I am trying to implement an efficient group by alogrithm from Most efficient method to groupby on an array of objects and trying to put the types.我正在尝试通过算法从最有效的方法到 groupby 在对象数组上实现一个有效的分组,并尝试放置类型。 But I get the error:但我得到了错误:

T[keyof T] cannot be used to index {}

Here is my attempt这是我的尝试

 static groupBy<T>(xs:T[], key: keyof T) {
        return xs.reduce((rv, x)=> {
            (rv[x[key]] = rv[x[key]] || []).push(x);
            return rv;
        }, {});
    };

rv: any rv will be any . rv: any rv 都将是any

class A {
  static groupBy<T>(xs: T[], key: keyof T) {
    return xs.reduce((rv: any, x) => {
      (rv[x[key]] = rv[x[key]] || []).push(x);
      return rv;
    }, {});
  }
}

How to use it:如何使用它:

interface Person {
  name: string;
  age: number;
  salary: number;
}
const data: Person[] = [
  {name:"deepak", age: 30, salary: 2000},
  {name:"deepak1", age: 32, salary: 1000},
  {name:"deepak", age: 29, salary: 3000}
]
class A {
  static groupBy<T>(xs: T[], key: keyof T) {
    return xs.reduce((rv: any, x) => {
      (rv[x[key]] = rv[x[key]] || []).push(x);
      return rv;
    }, {});
  }
}
console.log(A.groupBy(data, "name"))

Defination from Lodash: Lodash的定义:

groupBy(
            predicate?: Lodash.ListIterator<T, boolean> | Lodash.DictionaryIterator<T, boolean> | string,
            thisArg?: any,
        ): Lodash.Dictionary<T[]>;
        groupBy<R extends {}>(predicate?: R): Lodash.Dictionary<T[]>;

Sync group return an object and object cant have any other element as key other than string|number.同步组返回 object 和 object 不能将任何其他元素作为键,而不是字符串|数字。 Else you can follow more genric solution.否则,您可以遵循更多通用解决方案。

interface Any<T> {
  [key: string]: T[];
}
interface SMap<T> {
  [key: string]: T;
}
class A {
  static groupBy<T extends SMap<string>>(xs: T[], key: keyof T) {
    return xs.reduce((rv: Any<T>, x) => {
      if (!rv[x[key]]) {
        rv[x[key]] = [];
      }
      rv[x[key]].push(x);
      return rv;
    }, {});
  }
}

if you don't want to use any , you need properly define types to tell that reducer can combine data.如果您不想使用any ,则需要正确定义类型以告诉 reducer 可以组合数据。

function groupBy<T extends {[LK in K]: keyof any}, K extends keyof T>(xs:T[], key: K) {
  return xs.reduce<{[LK2 in T[K]]?: Array<T>}>((rv, x) => {
            (rv[x[key]] = rv[x[key]] || [])?.push(x);
            return rv;
        }, {});
};

const result = groupBy([{ test: 'key' }], 'test');

result.key?.length; // 1

T is an object where type of passed key is something that can be used as a key (for rv). T 是 object,其中传递的密钥类型是可以用作密钥的东西(对于 rv)。

for reducer - it starts with an empty object - we need to says that result will be an object where value of the key is an array of entities from the xs {[LK2 in T[K]]?: Array<T>}对于减速器 - 它以空 object 开头 - 我们需要说结果将是 object ,其中键的值是来自 xs {[LK2 in T[K]]?: Array<T>}的实体数组

Not as short as the original.没有原版那么短。 However, it does not use "any" or "as" casting.但是,它不使用“any”或“as”强制转换。 It also supports any data type for the group key, hence, unknown.它还支持组键的任何数据类型,因此是未知的。

export function groupBy<T>(xs: T[], key: keyof T): Map<unknown, T[]> {
  return xs.reduce((rv: Map<unknown, T[]>, entity: T) => {
    const value = entity[key];
    if (rv.has(value)) {
      rv.get(value)?.push(entity)
    } else {
      rv.set(value, [entity]);
    }
    return rv;
  }, new Map());
};

example of usage:用法示例:

const badgesByTypes = groupBy(currentState.badges, 'type');
for (const [key, values] of badgesByTypes.entries()) {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM