2016-06-08 53 views
27

我想迭代一个打字稿地图,但我不断收到错误,我找不到任何解决方案,但这样一个微不足道的问题。迭代手稿地图

我的代码是:

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)

我使用角CLI beta5的和打字稿1.8 .10,我的目标是es5。 有没有人有这个问题?

+4

看到这个答案github https://github.com/Microsoft/TypeScript/issues/3164#issuecomment-104443321 – yurzui

+0

谢谢。还有点奇怪,他们仍在讨论这个问题。 – mwe

回答

46

你可以使用Map.prototype.forEach((value, key, map) => void, thisArg?) : void代替

使用方法如下:

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

刚刚碰到了这个。看起来TypeScript看起来不符合map迭代的规范,至少根据[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)一个for-for循环。 '.forEach'是次优的,因为你不能打破它,AFAIK – Samjones

+3

我的经验表明.forEach根本行不通。它忽略了整个循环,没有任何反应。 – peterh

+0

如何用角度表达式打印此对象? – Lobato

1

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

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

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

+0

如何在html中迭代地图?它似乎并没有工作。

{{key}}.
powerfade917

+0

@ powerfade917它不起作用,它只适用于数组,因为角是一堆垃圾。但问这是一个新问题,所以你会学习,角度不是一堆垃圾,但你必须将它转换为一个数组。请注意,你也不是编程的顶端,因为你似乎无法区分角度和打字稿。 – peterh

12

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

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

它也适用于其他类型的键,不仅用于'string',而且键不会转换为'string'。 – kcpr

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

我使用的是最新的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); 
} 
+0

你能否确认你首先必须在'tsconfig.json'中设置''downlevelIteration“:true'? –

+1

但是我没有'downlevelIteraton'集,我的目标是'es2017'。 – lazieburd

0

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的类型将被自动推断。


为什么这是默认关闭的?据打字稿贡献者@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("target": "es2015"tsconfig.jsontsc --target ES2015)或更高版本,使downlevelIteration是一个没有脑子,但如果你的目标ES5/ES3,你可能标杆确保迭代器支持不会影响性能(如果是这样,那么最好使用Array.from转换或forEach或其他解决方法)。