MapToIterable in Angular pipe with TypeScript

2019-08-04 09:01发布

问题:

Trying to implement a pipe in Angular. After realizing ngFor wouldn't work with maps. Some research led me to believe that future features were coming to deal with that but in the meantime a mapToIterable pipe was the answer.

I have the following code:

import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'mapToIterable'
})
export class MapToIterablePipe implements PipeTransform  {
  transform(map: Map<string, Object>, args: any = []): any {
    const a: any[] = [];
    console.log(map.keys());  // <- works as expected
    for (const k in map) {
      if (map.has(k)) {
        console.log("hello");  // <- never executes
        console.log(k);
        a.push({key: k, val: map.get(k)});
      }
    }
    console.log(a); // <- always empty
    return a;
  }
}

export const MAPTOITERABLE_PROVIDERS = [
  MapToIterablePipe
];

map.keys() gives me a list of correct keys, but nothing else works.

Any suggestion on how to diagnose why my loop isn't filling the array correctly?

回答1:

Map 'keys' are not object keys and cannot be obtained with Object.keys() or in operator.

Considering that map.keys() returns an iterable, it should be

for (const key of Array.from(map.keys())) {
  // this check is unneeded
  // if (map.has(k)) {
  ...
}

Or in TypeScript 2.3 with downlevelIteration option,

for (const key of map.keys()) { ... }

Or just

const a: any[] = Array.from(map.entries()).map(([key, val]) => ({ key, val }));

Due to how TypeScript implements spread operator, [...iterable] won't work the same way as Array.from(iterable) in 2.2 and lower.