2

I have "noUncheckedIndexedAccess": true in my tsconfig.json. The whole point of the switch is to force the check of existence of the item at an index before accessing it.

I struggle to do the check for object with a variable key:

Say I have the following structure:

const items: Record<string, {name: string}> = {
  '123': {
    name: 'asdf'
  }
}

when I try to check the existence using a literal key, the type narrowing works ok:

if (items['123']) {
  // OK: Compiles no problem
  console.log(items['123'].name)
}

If I try to check the existence using a variable key, the compiler starts to complain.

const id = '123';
if (items[id]) {
  // ERROR: items[id] - Object possibly undefined
  console.log(items[id].name)
}

Why is it not possible to check the existence that way?

I tried even different checks:

if (id in items) {}
if (items.hasOwnProperty(id)) {}
if (typeof items[id] !== 'undefined') {}

no luck there.

The only thing that worked was

const id = '123';
const item = items[id];
if (item) {
  // OK
  console.log(item.name)
}

I find it a bit too chatty, though.

▶️ Examples above in TypeScript Playground

Environment: TypeScript v4.5.4

jhrdka
  • 45
  • 4

1 Answers1

4

There's an issue on GitHub that's essentially describing this exact situation:

Can't narrow T | undefined into T with a falsy check when using --noUncheckedIndexedAccess

That issue is closed as a duplicate of this issue, which is still open as of February 2022:

Discriminant property type guard not applied with bracket notation

Based on the discussion on that second issue and other linked issues, it sounds like this is a known limitation due to the performance overhead that would be required to implement this in the type checker, e.g. here:

Declined due to performance reasons. Since it should almost always be possible to write const j = list[i] instead, this shouldn't be too burdensome.

Given that the issue is still open, it seems possible that this may be re-addressed at some point to support the behavior that you expect.

Donut
  • 110,061
  • 20
  • 134
  • 146