'Optional chaining operator weird behaviour
I am experiencing some weird behaviour in TypeScript (v4.6.2). Why does (a) work but (b) and (c) don't?
const a: string[] | null = []
if (a?.length > 1) {
console.log(1)
}
const b = [] as (string[] | null)
if (b?.length > 1) {
console.log(1)
}
const c: string[] | null = [] as (string[] | null)
if (c?.length > 1) {
console.log(1)
}
Solution 1:[1]
Case A works because the compiler is smart enough to see that const a is actually [] and not null, although your explicit type declaration says something different.
In case b and c you're casting the value, telling the compiler that your variable might be null. In that case b?.length might resolve to undefined. And undefined > 1 is not a valid comparison.
Solution 2:[2]
In case A the assignment happens after the type has been declared, so typescript is able to figure out that a is actually a string[]. Therefore you don't even need the optional chaining operator there and can just use:
if (a.length > 1) {
console.log(1)
}
In the other cases, you first assign and then cast to a type, so typescript considers the type to be string[] | null. The expression b?.length returns undefined for null values, so you end up with a comparison undefined > 1 which is invalid. To fix this, you should rewrite the condition as:
if (b && b.length > 1) {
console.log(1)
}
Here we make sure that b is not null before accessing the length property and doing the comparison.
Solution 3:[3]
The error is Object is possibly 'undefined'. This feature is called "strict null checks". In case A, the compiler can understand the value cant to be null, while in b and c the compile fails to determine and throws error Object is possibly 'undefined' as you try to get .length method of undefined
You can use the non-null assertion operator! to coerce away those types like b!?.length > 1
const a: string[] | null = []
if (a?.length > 1) {
console.log(1)
}
const b = [] as (string[] | null)
if (b!?.length > 1) {
console.log(1)
}
const c: string[] | null = [] as (string[] | null)
if (c!?.length > 1) {
console.log(1)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | hendra |
| Solution 2 | szaman |
| Solution 3 |

