I defined two interfaces. The first one has an optional field, the second one has an index signature:
interface A {
foo?: { bar: number };
}
interface B {
[s: string]: { bar: number };
}
Why does the first interface give me a result of type number | undefined
when I access the property using optional chaining, whereas the second one gives only type number
?
const a: A = {};
const aa = a.foo?.bar;
// const aa: number | undefined
const b: B = {};
const bb = b.foo?.bar;
// const bb: number
Because B is indexed by
[s: string]
, it believe that any valid string key will result in the value of{ bar: number }
being accessed. So, withit thinks that the
foo
property will always exist - it'll never fail and turn intoundefined
via optional chaining.In contrast, with A's:
Since the
foo
property is optional here, it's not sure to exist (to Typescript), so the?.
may result in no property being found andundefined
being the result.You can make it clear that not all properties on
B
will necessarily have thebar
object by alternating withundefined
in the object value type:resulting in
bb
being typed asnumber | undefined
.