I'm using the function below to compare two maps. What's interesting is that the code inside for loop is never executed. So, console.log(key,val) code is never executed. Of course I made sure that the maps I'm comparing are not empty and are of same size to force execution of the code inside the for loop. Am I making a really silly mistake or am missing a deep concept?
private compareMaps(map1, map2) {
        var testVal;
        if (!(map1 && map2)) {
            return false;
        }
        if (map1.size !== map2.size) {
            return false;
        }
        for (var [key, val] of map1) {
            testVal = map2.get(key);
            console.log(key, val);
            if (testVal !== val || (testVal === undefined && !map2.has(key))) {
                return false;
            }
        }
        return true;
    }
                What's interesting is that the code inside for loop is never executed. Am I making a really silly mistake or am missing a deep concept?
You're missing the fact that...
for...of does not work on Map in TypeScript prior to ES6When it targets ECMAScript prior to ES6, the TypeScript compiler transpiles the for...of statement into a for loop. 
This code:
for (var [key, val] of map) {
    console.log(key);
}
Becomes this code:
for (var _i = 0, map_1 = map; _i < map_1.length; _i++) {
    var _a = map_1[_i], key = _a[0], val = _a[1];
    console.log(key);
}
What to do?
Option 1: When we must target ECMAScript prior to ES6, the forEach function can be a suitable alternative to the for...of loop. Beware though that forEach has subtle differences from for...of (e.g. exiting early, async/await).
map.forEach((val, key) => { 
    console.log(key + ":" + val);
});
Option 2: When we must target ECMAScript prior to ES6, and we must have the exact behavior of for...of, the answer by John Weisz makes sense: convert the Map to an Array and iterate the Array with for...of.
Option 3: When we can target ECMAScript ES6 or later, use the for...of loop directly on the Map.
If the requirement is Map equality, consider the every function. That takes care of the need to break in the iteration, because every immediately returns when it finds the first false.
If order matters to the comparison, use every like this:
function areEqual<K,V>(map1: Map<K,V>, map2: Map<K,V>) { 
    if(!map1 || !map2) return false;
    const array1 = Array.from(map1.entries());
    const array2 = Array.from(map2.entries());
    return array1.every(([k1, v1], index) => {
        const [k2, v2] = array2[index];
        return k1 === k2 && v1 === v2;
    });
}
If order does not matter, then we want set equality; use every like this: 
function areSetEqual<K, V>(map1: Map<K, V>, map2: Map<K, V>) { 
    if(!map1 || !map2) return false;
    const array1 = Array.from(map1.entries());
    const array2 = Array.from(map2.entries());
    return array1.length === array2.length &&
        array1.every(([k1, v1]) => map2.get(k1) === v1);
}
Here is a demo of the functions in action:
const map1 = new Map([["key1", "val1"], ["key2", "val2"]]);
const map2 = new Map([["key1", "val1"], ["key2", "val2"]]);
const map3 = new Map([["key2", "val2"], ["key1", "val1"]]);
console.log(areEqual(map1, map2)); // true
console.log(areEqual(map1, map3)); // false
console.log(areSetEqual(map1, map2)); // true
console.log(areSetEqual(map1, map3)); // true
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With