Can’t narrow the type of an object property even after checking it with a type guard

The problem is that the compiler doesn’t know how to do narrowing on an object property like IceCreams[item] where you are indexing with a key whose type isn’t known to be a specific literal type. TypeScript is only following the type of the index, not the identity. And the type of item is string. If you have item1 and item2, both of type string, then checking IceCreams[item1] wouldn’t let you conclude anything about IceCreams[item2], right? And since TypeScript can’t tell the difference between item1 vs item2 or item vs item, it can’t narrow. This is a known limitation of TypeScript reported at microsoft/TypeScript#10530. Maybe someday it will be addressed. But for now, there’s an easy workaround:

Just copy the value into a new variable, so that the problematic indexing occurs only once:

iceCreamKeys.forEach(item => {
    const x = IceCreams[item];
    if (x.natural) {
        console.log(x.naturalComponent)  // okay
    }
})

Playground link to code

Leave a Comment