ค้นหาเว็บไซต์

พจนานุกรม - การวนซ้ำบน Typescript Map


ฉันกำลังพยายามวนซ้ำในแผนที่ของ TypeScript แต่ฉันมักจะเจอข้อผิดพลาดและยังหาวิธีแก้ปัญหาสำหรับปัญหาเล็กน้อยแบบนี้ไม่ได้เลย

รหัสของฉันคือ:

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 มีใครเคยเจอปัญหานี้ไหม?

คำตอบ #1

คุณสามารถใช้ Map.prototype.forEach((value, key, map) => void, thisArg?) : void แทนได้

ใช้มันแบบนี้:

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

คำตอบ #2

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

คำตอบ #3

เพียงแค่ใช้เมธอด Array.from() เพื่อแปลงมันเป็น Array:

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

คำตอบ #4

นี่ใช้ได้ผลสำหรับฉัน เวอร์ชันของ TypeScript: 2.8.3

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

คำตอบ #5

การใช้ 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]));

คำตอบ #6

ตามบันทึกการอัปเดต TypeScript 2.3 เกี่ยวกับ "--downlevelIteration ใหม่"

for..of statements, การสลาย Array, และองค์ประกอบ Spread ใน Array, Call, และ New expressions รองรับ Symbol.iterator ใน ES5/E3 หากมีเมื่อใช้ --downlevelIteration

นี่ไม่ได้เปิดใช้งานโดยค่าเริ่มต้น! เพิ่ม "downlevelIteration": true ลงใน tsconfig.json ของคุณ หรือใช้ตัวเลือก --downlevelIteration กับ tsc เพื่อรับการสนับสนุนตัวทำซ้ำอย่างเต็มรูปแบบ

เมื่อมีสิ่งนี้อยู่ คุณสามารถเขียน for (let keyval of myMap) {...} และประเภทของ keyval จะถูกอนุมานโดยอัตโนมัติ

ทำไมสิ่งนี้ถึงถูกปิดโดยค่าเริ่มต้น? ตามที่ผู้ร่วมพัฒนา TypeScript @aluanhaddad กล่าว

มันเป็นทางเลือกเพราะมันมีผลกระทบอย่างมากต่อขนาดของโค้ดที่สร้างขึ้น และอาจส่งผลต่อประสิทธิภาพ สำหรับการใช้งาน iterable ทั้งหมด (รวมถึง arrays)

ถ้าคุณสามารถตั้งเป้าเป็น ES2015 ("target": "es2015" ใน tsconfig.json หรือ tsc --target ES2015) หรือเวอร์ชันที่ใหม่กว่า การเปิดใช้งาน downlevelIteration เป็นเรื่องง่าย แต่ถ้าคุณตั้งเป้าเป็น ES5/ES3 คุณอาจต้องวัดประสิทธิภาพเพื่อให้แน่ใจว่าการสนับสนุน iterator ไม่ส่งผลกระทบต่อประสิทธิภาพ (ถ้ามี ผลกระทบ คุณอาจใช้วิธีการแปลงด้วย Array.from หรือ forEach หรือวิธีแก้ปัญหาอื่น ๆ จะดีกว่า)

คำตอบ #7

นี่ใช้ได้ผลสำหรับฉัน

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

คำตอบ #8

คุณยังสามารถใช้วิธี array map กับ iterable ของ Map.entries() ได้ด้วย:

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

นอกจากนี้ ตามที่ได้กล่าวไว้ในคำตอบอื่น ๆ คุณอาจต้องเปิดใช้งานการวนซ้ำระดับต่ำในไฟล์ tsconfig.json ของคุณ (ภายใต้ตัวเลือกตัวคอมไพเลอร์):

  "downlevelIteration": true,

บทความที่เกี่ยวข้อง