使用Map实例按属性名称返回不同对象的数组?

时间:2019-03-23 19:50:17

标签: javascript node.js typescript slice

此实现似乎运行良好(Stackblitz):

    /**
     * Returns all the elements that are distinct by the 
     * `property` value.  Note that the implementation uses a `Map<string, E>` to
     * index the entities by key.  Therefore the more recent occurences 
     * matching a key instance will overwrite the previous ones.
     * 
     * @param property The name of the property to check for distinct values by.
     * @param entities The entities in the array.
     * 
     * @example
     * ```
     * let todos:Todo = [{ id: 1, "Lets do it!" }, {id: 2, "All done!"}];
     * let dtodos:Todo[] = distinct<Todo>(todos, 'id');
     */
    export function distinct<E>(entities:E[], property:string):E[] {
        let map:Map<string, E> = new Map();
        entities.forEach((e:E)=>{
            map.set(e[property], e);
        });
        return Array.from(map.values());
    }

唯一的问题是VSCode在e[property]部分下呈波浪状绘制红色,错误消息为:

  

元素隐式地具有“ any”类型,因为类型“ {}”没有索引签名。ts(7017)

有办法摆脱它吗?

图书馆馆藏实施

我在此轻量级状态管理器中为对象和实体添加了最新建议的实现:

https://www.npmjs.com/package/@fireflysemantics/slice

npm i @fireflysemantics/slice
...
import {distinct} from '@fireflysemantics/slice/utilities';

演示

https://stackblitz.com/edit/typescript-slice-distinct

2 个答案:

答案 0 :(得分:4)

错误消息有点误导。他的问题是,不能像定义e[property]那样确保string的类型为Map

使any类型的Map中的键具有很大的灵活性,您也无法确定值的类型。

另外,我将property参数键入为keyof E,以便TS确保我只能粘贴该类型的有效属性名称。

function distinct<E>(entities:E[], property:keyof E):E[] {
    let map:Map<any, E> = new Map();
    entities.forEach((e:E)=>{
        map.set(e[property], e);
    });
    return Array.from(map.values());
}

答案 1 :(得分:2)

基于Thomas'的答案,我们可以简化两者:

  • JavaScript代码:一次构造"display": "standalone"
  • TypeScript类型:添加Map,我们可以转换用作K extends keyof E构造函数输入参数的元组([E[K], E]),并删除Map类型使用。

代码在这里:

any

调用function distinct<E, K extends keyof E>(entities: E[], property: K): E[] { const entitiesByProperty = new Map(entities.map(e => [e[property], e] as [E[K], E])); return Array.from(entitiesByProperty.values()); } 时,无需指定通用类型,因为可以推断出它们。这是一个工作示例:

distinct()