2016-06-08 52 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或其他解決方法)。