遍历 Typescript Map

Iterating over Typescript Map

我正在尝试遍历 typescript 映射,但我不断收到错误,而且对于这样一个微不足道的问题,我还找不到任何解决方案。

我的代码是:

myMap : Map<string, boolean>;
for(let key of myMap.keys()) {
   console.log(key);
}

我收到错误:

Type 'IterableIteratorShim<[string, boolean]>' is not an array type or a string type.

完整堆栈跟踪:

 Error: Typescript found the following errors:
  /home/project/tmp/broccoli_type_script_compiler-input_base_path-q4GtzHgb.tmp/0/src/app/project/project-data.service.ts (21, 20): Type 'IterableIteratorShim<[string, boolean]>' is not an array type or a string type.
    at BroccoliTypeScriptCompiler._doIncrementalBuild (/home/project/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:115:19)
    at BroccoliTypeScriptCompiler.build (/home/project/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
    at /home/project/node_modules/broccoli-caching-writer/index.js:152:21
    at lib$rsvp$$internal$$tryCatch (/home/project/node_modules/rsvp/dist/rsvp.js:1036:16)
    at lib$rsvp$$internal$$invokeCallback (/home/project/node_modules/rsvp/dist/rsvp.js:1048:17)
    at lib$rsvp$$internal$$publish (/home/project/node_modules/rsvp/dist/rsvp.js:1019:11)
    at lib$rsvp$asap$$flush (/home/project/node_modules/rsvp/dist/rsvp.js:1198:9)
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

我正在使用 angular-cli beta5 和 typescript 1.8.10,我的目标是 es5。 有人遇到过这个问题吗?

您可以改用 Map.prototype.forEach((value, key, map) => void, thisArg?) : void

这样使用:

myMap.forEach((value: boolean, key: string) => {
    console.log(key, value);
});

如果你不太喜欢嵌套函数,你也可以遍历键:

myMap : Map<string, boolean>;
for(let key of myMap) {
   if (myMap.hasOwnProperty(key)) {
       console.log(JSON.stringify({key: key, value: myMap[key]}));
   }
}

请注意,您必须使用 hasOwnProperty 过滤掉非键迭代,如果不这样做,您会收到警告或错误。

只需使用 Array.from() 方法将其转换为 Array:

myMap : Map<string, boolean>;
for(let key of Array.from( myMap.keys()) ) {
   console.log(key);
}

居中

for (let [key, value] of map) {
    console.log(key, value);
}

for (let entry of Array.from(map.entries())) {
    let key = entry[0];
    let value = entry[1];
}

我正在使用最新的 TS 和节点(分别为 v2.6 和 v8.9),我可以:

let myMap = new Map<string, boolean>();
myMap.set("a", true);
for (let [k, v] of myMap) {
    console.log(k + "=" + v);
}

根据 TypeScript 2.3 release notes on "New --downlevelIteration":

for..of statements, Array Destructuring, and Spread elements in Array, Call, and New expressions support Symbol.iterator in ES5/E3 if available when using --downlevelIteration

默认情况下未启用!"downlevelIteration": true添加到您的tsconfig.json,或将--downlevelIteration标志传递给tsc , 以获得完整的迭代器支持。

有了这个,你可以写 for (let keyval of myMap) {...} 并且 keyval 的类型将被自动推断出来。


为什么默认关闭此功能?根据 TypeScript 贡献者 @aluanhaddad

It is optional because it has a very significant impact on the size of generated code, and potentially on performance, for all uses of iterables (including arrays).

如果您可以定位 ES2015(tsconfig.jsontsc --target ES2015 中的"target": "es2015")或更高版本,启用 downlevelIteration 是一个明智的选择,但如果您定位ES5/ES3,您可以进行基准测试以确保迭代器支持不会影响性能(如果确实如此,您最好使用 Array.from 转换或 forEach 或其他一些解决方法)。

使用Array.from, Array.prototype.forEach(), and arrow functions:

迭代:

Array.from(myMap.keys()).forEach(key => console.log(key));

迭代:

Array.from(myMap.values()).forEach(value => console.log(value));

遍历 条目:

Array.from(myMap.entries()).forEach(entry => console.log('Key: ' + entry[0] + ' Value: ' + entry[1]));

这对我有用。打字稿版本:2.8.3

for (const [key, value] of Object.entries(myMap)) { 
    console.log(key, value);
}

只是在 HTML 文档中使用它的简单说明。

如果你有一个类型(键,数组)的映射,那么你可以这样初始化数组:

public cityShop: Map<string, Shop[]> = new Map();

要迭代它,您可以从键值创建一个数组。

只需将其用作数组,如:

keys = Array.from(this.cityShop.keys());

然后,在HTML中,您可以使用:

*ngFor="let key of keys"

在此循环中,您只需使用以下命令获取数组值:

this.cityShop.get(key)

完成!

这对我有用。

Object.keys(myMap).map( key => {
    console.log("key: " + key);
    console.log("value: " + myMap[key]);
});

您还可以将数组映射方法应用于 Map.entries() 可迭代对象:

[...myMap.entries()].map(
     ([key, value]: [string, number]) => console.log(key, value)
);

此外,如其他答案所述,您可能必须在 tsconfig.json(在编译器选项下)中启用下层迭代:

  "downlevelIteration": true,

在 Typescript 3.5 和 Angular 8 LTS 上,需要按如下方式转换类型:

for (let [k, v] of Object.entries(someMap)) {
    console.log(k, v)
}

我尝试使用 Array.from( myMap.keys() ) 在使用 node.js 实现的 VSCode 扩展中获取键数组,但它没有用,即使在添加 "downlevelIteration": true 之后也是如此根据 和其他人的建议,我的 tsconfig.json 将目标设置为 es2017

最终起作用的是 建议使用 Object.keys:

let keys = Object.keys(myMap);