Max Yankov
Max Yankov

Reputation: 13327

Why does Typescript infer type of a value retrieved by absent key without undefined?

I have this example code:

const example: { [key: string]: string } = { a: 'abc' }

const b = example['b']

At runtime, b would obviously be equal undefined, but at compile type, Typescript infers b type to be just string and not string|undefined. This seems like an error to me.

Why doesn't it infer it as string|undefined, and how can I force it to do so?

Upvotes: 2

Views: 278

Answers (3)

Aplet123
Aplet123

Reputation: 35560

You broaden the type by casting it to {[key: string]: string}, so from a type perspective, 'b' is as valid a key as 'a'. Omit the type and let typescript infer a narrower type, and an error will be thrown:

const example = { a: 'abc' };

// error: property 'b' does not exist
const b = example['b'];

There's a discussion about adding | undefined to index lookups on GitHub issue #9235, and it was actually resolved with a noUncheckedIndexedAccess flag added in typescript 4.1. If it's set, then b will be string | undefined, even in your example.

Playground link.

Upvotes: 3

Orelsanpls
Orelsanpls

Reputation: 23575

It's not an error. Considering typing only : 'b' could be a valid key.

The type { [key: string]: string } specifycally tells Typescript that example can contains any key name.

Typescript is not analyzing your variable. It only compare type and see if they match.


In the following example typescript show you an error. Because you list the keys that can exists or not.

type keys = 'a' | 'foo';

const example: { [key in keys]?: string } = { a: 'abc' }

const b = example['b']

enter image description here

Upvotes: 3

Michiel de Vos
Michiel de Vos

Reputation: 171

You are casting example to be of { [key: string]: string } type. In other words, you are telling typescript it is always a string. There is no way of typescript analysing if it is really on there or not as its a statically typed language.

Upvotes: 0

Related Questions