Подтвердить что ты не робот

Итерация по Typescript Карта

Я пытаюсь перебрать карту машинописного текста, но получаю ошибки и пока не могу найти решения для такой тривиальной проблемы.

Мой код:

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

И я получаю сообщение об ошибке:

Тип 'IterableIteratorShim & lt; [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 и машинописный текст 1.8.10, и моя цель - es5. У кого-нибудь была эта проблема?

4b9b3361

Ответ 1

Вместо Map.prototype.forEach((value, key, map) => void, thisArg?) : void можно использовать

Используйте его следующим образом:

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

Ответ 2

Просто используйте метод Array.from(), чтобы преобразовать его в массив:

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

Ответ 3

Используя 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]));

Ответ 4

Это сработало для меня. Версия TypeScript: 2.8.3

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

Ответ 5

В примечаниях к выпуску TypeScript 2.3 в --downlevelIteration "Новый --downlevelIteration ":

for..of statements, Array Destructuring и Spread в массивах Array, Call и New используются Symbol.iterator в ES5/E3, если они доступны при использовании --downlevelIteration

По умолчанию это отключено! Добавьте "downlevelIteration": true для вашего tsconfig.json или --downlevelIteration флаг --downlevelIteration в tsc, чтобы получить полную поддержку итератора.

При этом вы можете писать for (let keyval of myMap) {...} и keyval type будут автоматически выведены.


Почему это отключено по умолчанию? Согласно составителю TypeScript @aluanhaddad,

Это необязательно, поскольку оно оказывает существенное влияние на размер сгенерированного кода и потенциально на производительность для всех применений итераций (включая массивы).

Если вы можете настроить таргетинг на ES2015 ("target": "es2015" в tsconfig.json или tsc --target ES2015) или более поздней tsc --target ES2015, включение downlevelIteration - это без проблем, но если вы ориентируетесь на ES5/ES3, вы можете проверить, поддержка итератора не влияет на производительность (если это так, вам может быть лучше с Array.from преобразование или forEach или какое-либо другое обходное решение).

Ответ 6

ES5

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

ES6

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

Ответ 7

Я использую последние TS и node (v2.6 и v8.9 соответственно), и я могу сделать:

let myMap = new Map<string, boolean>();
myMap.set("a", true);
for (let [k, v] of myMap) {
    console.log(k + "=" + v);
}

Ответ 8

Это сработало для меня.

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

Ответ 9

Простое объяснение, чтобы сделать это из HTML, если у вас есть карта типов (ключ, массив):

Я инициализирую массив таким образом:

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

И для перебора над ним я создаю массив из значений ключа: - просто используйте его как массив с помощью: keys = Array.from(this.cityShop.keys());

Затем, в HTML, я могу использовать:

*ngFor="let key of keys"

Внутри этого кучка я просто получаю значение массива с помощью this.cityShop.get(key)

И... сделано!

Ответ 10

Если вам не нравятся вложенные функции, вы также можете перебирать ключи:

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

Обратите внимание, что вы должны отфильтровать инертные ключи без ключа с помощью hasOwnProperty, если вы этого не сделаете, вы получите предупреждение или ошибку.