我试图迭代一个typescript映射,但我一直得到错误,我找不到任何解决方案,这样一个微不足道的问题。

我的代码是:

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

然后我得到Error:

类型'IterableIteratorShim<[string, boolean]>'不是数组类型或字符串类型。

全栈跟踪:

 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。 有人遇到过这个问题吗?


当前回答

使用Array.from、Array.prototype.forEach()和箭头函数:

遍历键:

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]));

其他回答

使用Array.from、Array.prototype.forEach()和箭头函数:

遍历键:

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]));

es6

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

es5

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

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

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

根据TypeScript 2.3发布说明“New——downlevelIteration”:

for..of语句、数组解构和数组、Call和New表达式中的展开元素支持Symbol。在ES5/E3中使用——downlevelIteration时可用的迭代器

默认情况下不启用!在你的tsconfig中添加"downlevelIteration": true。或者将——downlevelIteration标志传递给tsc,以获得完整的迭代器支持。

有了这些,您可以编写for (let keyval of myMap){…}和keyval的类型将被自动推断。


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

它是可选的,因为它对生成的代码的大小有非常重要的影响,并且对于所有使用可迭代对象(包括数组)的性能也有潜在的影响。

如果你可以在tsconfig中瞄准ES2015 ("target": " ES2015 ")。如果你的目标是ES5/ES3,你可以进行基准测试,以确保迭代器支持不会影响性能(如果会影响性能,你最好使用Array.from conversion或forEach或其他变通方法)。

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

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

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