I\'m trying to understand why TypeScript is giving me the following error: Object is possibly \'undefined\'
Here\'s the code snippet:
If you query for a key not in the map, you will get undefined. Not because the map holds an undefined value, but because it does not hold a value at all.
Try
results.get(key)!
Or
results.get(key) as number
Becouse the compiler is not so smart to take into account behavior of Map.
There is no type guarding for Map.has()
See this issue or this issue.
You can fix the issue by having a fallback of 0
, -1
or whatever you think would be best for your code.
const mergedDepsObj: { [key: string]: string } = {}
const results: Map<string, number> = new Map();
Object.keys(mergedDepsObj).forEach((key: string) => {
results.has(key) ? results.set(key, (results.get(key) || 0) + 1) : results.set(key, 0);
})
However, above being said, we make our own type guard with help from this comment.
interface Map<K, V> {
// Works if there are other known strings.
has<KnownKeys extends K, CheckedString extends K>(this: MapWith<string, V, any>, key: CheckedString): this is MapWith<K, V, CheckedString | KnownKeys>
has<CheckedString extends K>(this: Map<string, V>, key: CheckedString): this is MapWith<K, V, CheckedString>
}
interface MapWith<K, V, DefiniteKey extends K> extends Map<K, V> {
get(k: DefiniteKey): V;
}
const mergedDepsObj: { [key: string]: string } = {}
const results: Map<string, number> = new Map();
Object.keys(mergedDepsObj).forEach((key: string) => {
results.has(key) ? results.set(key, results.get(key) + 1) : results.set(key, 0);
})
We can see it in action here