Typescript 맵 반복


134

타이프 스크립트 맵을 반복하려고하는데 계속 오류가 발생하고 사소한 문제에 대한 해결책을 아직 찾을 수 없습니다.

내 코드는 다음과 같습니다.

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

그리고 오류가 발생합니다.

'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입니다. 누구든지이 문제가 있었습니까?


4
이 GitHub의에서 답변을 참조 github.com/Microsoft/TypeScript/issues/...
yurzui

답변:


210

Map.prototype.forEach((value, key, map) => void, thisArg?) : void대신 사용할 수 있습니다.

다음과 같이 사용하십시오.

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

15
방금 만났어요. TypeScript가 적어도 for-of 루프를 지정하는 MDN 에 따라 맵 반복에 대한 사양을 존중하는 것처럼 보이지 않습니다 . .forEach깰 수 없기 때문에
차선책입니다

14
왜 그 가치가 중요한지 모르겠습니다. 거꾸로 보인다.
Paul Rooney

@PaulRooney 아마도 Array.prototype.map.
Ahmed Fasih

1
필요한 것을 찾은 경우이 반복 프로세스를 중지하는 방법은 무엇입니까?
JavaRunner

36

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

1
위에 제공된 es6 버전은 엄격 모드에서 컴파일되지 않습니다.
Stephane

감사합니다.
Kitanga Nday

36

Array.from()방법을 사용 하여 다음으로 변환하십시오 Array.

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

5
맵 변환은 성능이 매우 많이 필요한 작업이며 기본적으로 컴파일러가 언어의 핵심 부분을 숨기는 문제를 해결하는 올바른 방법이 아닙니다. 그냥 <any>지도 -cast에 대한-의 그것을 반복합니다.
Kilves

1
주의 : 위의 @Kilves 제안이 맵을 "any"로 캐스팅하는 것이 우아한 해결 방법이라고 생각했습니다. 내가 그것을했을 때, 코드는 불만없이 컴파일되고 실행되었지만 Map은 실제로 반복되지 않았습니다. 루프의 내용은 실행되지 않았습니다. 여기서 Array.from()제안한 전략은 저에게 효과적이었습니다.
mactyr

난 나쁘지는 고려하고있는 중 하나가 나를 위해 일을하지 않았다, 그것도 시도 이다 ES6의 일부와 대부분의 브라우저에해야 "그냥 작품". 그러나 나는 우리의 앵글 오버로드가 ES6를 싫어하기 때문에 zone.js에서 작동하지 않게 만들기 위해 마법의 mumbo jumbo를 사용한다고 생각합니다. 한숨.
Kilves

28

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

2
왜 그런지 모르겠지만 Map <String, CustomeClass>와 같은 맵이 있습니다. Array.from (myMap.values ​​()). forEach (value => console.log (value));를 제외하고는 위의 방법 중 어느 것도 작동하지 않았습니다.
Rajashree Gr

27

이것은 나를 위해 일했습니다. TypeScript 버전 : 2.8.3

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

7
Object.entries (myMap)을 myMap.entries ()로 변경하여이 작업을 수행했습니다. .forEach 호출의 오류 처리 함정을 피하기 때문에이 답변을 좋아합니다.
encrest

2
귀하의 경우 지적 가치 target의가 tsconfig있다 es5하지만,와,이 오류가 발생합니다 es6올바르게 작동합니다. for (const [key, value] of myMap)타겟팅 할 때도 가능합니다es6
Benjamin Vogler

16

"New --downlevelIteration" 에 대한 TypeScript 2.3 릴리스 노트에 따라 :

for..of statements, Array Destructuring 및 Array, Call 및 New 표현식의 Spread 요소는 사용할 때 ES5 / E3에서 Symbol.iterator를 지원합니다. --downlevelIteration

이것은 기본적으로 활성화되어 있지 않습니다! 에 추가 하거나 플래그를에 전달 하여 전체 반복자 지원 "downlevelIteration": true을 받으십시오 .tsconfig.json--downlevelIterationtsc

이것으로 쓸 수 for (let keyval of myMap) {...}있고 keyval의 유형이 자동으로 유추됩니다.


이 기능이 기본적으로 꺼져있는 이유는 무엇입니까? TypeScript 기고자 @aluanhaddad 에 따르면 ,

이터 러블 (배열 포함)의 모든 사용에 대해 생성 된 코드의 크기와 잠재적으로 성능에 매우 큰 영향을 미치기 때문에 선택 사항입니다.

당신이 ES2015 (타겟팅 할 수있는 경우 "target": "es2015"tsconfig.json또는 tsc --target ES2015) 이상을, 가능하게는 downlevelIteration생각할 필요 없다,하지만 당신은 ES5 / ES3을 대상으로하는 경우, 당신은 반복자 지원이, 실행하는 경우, 당신은 더 나은 수 있습니다 (하지 않는 성능에 영향을 확인하기 위해 벤치 마크를 수도 와 떨어져 Array.from전환 또는 forEach) 또는 다른 해결 방법.


Angular를 사용할 때 이것을 활성화하는 것이 괜찮거나 위험합니까?
Simon_Weaver

9

이것은 나를 위해 일했습니다.

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

2
이것으로 키는 항상 문자열이 될 것입니다
Ixx

8

최신 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);
}

당신은 당신이 첫번째 세트로했다 확인할 수 있습니다 "downlevelIteration": true당신에 tsconfig.json?
Ahmed Fasih

3
나는 downlevelIteraton설정 하지 않았지만 내 목표는 es2017입니다.
lazieburd

Map <string, CustomClass []> 요소에 대해이 작업을 수행 할 수 없습니까? 컴파일러는 유형 또는 문자열 유형의 배열이 아니라고 말합니다.
Rajashree Gr

이 2.8에 나를 위해 작동하지 않습니다 - 내가 얻을Type 'Map<K, V>' is not an array type or a string type.
Simon_Weaver

3

Map.entries () 이터 러블에 배열 맵 메서드를 적용 할 수도 있습니다.

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

또한 다른 답변에서 언급했듯이 tsconfig.json (컴파일러 옵션 아래)에서 다운 레벨 반복을 활성화해야 할 수도 있습니다.

  "downlevelIteration": true,

이 기능은 TypeScript 2.3에서 도입되었습니다. TypeScript 1.8.10에서 문제가 발생했습니다
mwe

"downlevelIteration"을 사용할 수없는 경우 다음을 사용할 수 있습니다.const projected = Array.from(myMap).map(...);
Efrain

1

HTML 문서에서 사용하는 간단한 설명입니다.

유형의 맵 (키, 배열)이있는 경우 다음과 같이 배열을 초기화합니다.

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

그리고 그것을 반복하기 위해 키 값에서 배열을 만듭니다.

다음과 같이 배열로 사용하십시오.

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

그런 다음 HTML에서 다음을 사용할 수 있습니다.

*ngFor="let key of keys"

이 루프 내에서 다음을 사용하여 배열 값을 얻습니다.

this.cityShop.get(key)

끝난!



-1

중첩 된 함수가 마음에 들지 않으면 키를 반복 할 수도 있습니다.

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

를 사용하여 키가 아닌 반복을 필터링 hasOwnProperty해야합니다. 이렇게하지 않으면 경고 또는 오류가 발생합니다.


HTML에서 맵을 반복하는 방법은 무엇입니까? 전혀 작동하지 않는 것 같습니다. <div ng-repeat = "(key, value) in model.myMap"> {{key}}. </ div>
Shinya Koizumi

@ powerfade917 작동하지 않습니다. 각도는 쓰레기 더미이기 때문에 배열에서만 작동합니다. 그러나 이것을 새로운 질문으로 물어 보면 각도가 쓰레기 더미가 아니라 배열로 변환해야한다는 것을 알게 될 것입니다. 또한 앵귤러와 타이프 스크립트를 구별 할 수없는 것처럼 보이므로 프로그래밍의 최상위가 아닙니다.
peterh - 분석 재개 모니카
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.