admin管理员组

文章数量:1425781

TS Code

image = this.selectedItem.image.url || null;

The Error

TypeError: Cannot read property 'url' of null

My question is, why isn't the || null kicking in instead of it throwing a type error?

TS Code

image = this.selectedItem.image.url || null;

The Error

TypeError: Cannot read property 'url' of null

My question is, why isn't the || null kicking in instead of it throwing a type error?

Share Improve this question asked Oct 18, 2017 at 14:28 mls3590712mls3590712 8201 gold badge9 silver badges20 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 6

The shortest option you have is:

image = this.selectedItem && this.selectedItem.image && this.selectedItem.image.url || null;

If any of the && fails, you'll get null instead, but you have to check every "level" of the object you're trying to access.

This works because the && takes priority over || for order of operation. The above statement is similar to:

x = (((a.b) && (a.b.c)) && (a.b.c.url)) || null;

What you had, on the other hand, was similar to:

x = (a.b.c.url) || null;

You can't get url if a.b does not have a property c. That's what the error was thrown on, and that's not something the "or" at the end can catch.

I think you're confused about what "short-circuit" means. Boolean operators are evaluated from left to right (&& before || but left-to-right otherwise) until the result is either definitely falsy or truthy, and then it stops without evaluating anything else. In your case, the error occurs while this.selectedItem.image.url is being evaluated, and the || operator is never reached.

JavaScript lacks a null/undefined-coalescing operator such as the Elvis operator "?.", which would let you do something like this.selectedItem?.image?.url to prevent dereferencing undefined values.

Instead, you need to check each possible nested property for existence, if it is possible for them to be undefined:

image = (this.selectedItem && this.selectedItem.image && this.selectedItem.image.url) || null;

(I'm sure other answers have mentioned something like this... ah, yes, @Cerbrus has it) This is now short-circuiting in a way that helps you. As soon as one of those items is falsy, the whole parenthesized term evaluates as falsy without throwing an error. Then you get falsy-|| null which bees null, as you want.

Hope that helps; good luck!

You are checking this.selectedItem.image.url, but for that to be possible, you need to make sure that this.selectedItem and this.selectedItem.image exist first.

You could try the following:

image = this.selectedItem && this.selectedItem.image ? this.selectedItem.image.url || null : null;

You need to check also if the field image exists I think. Try to use ternary operator instead:

image = this.selectedItem.image ? this.selectedItem.image.url : null;

Because the error occurred when this.selectedItem.image.url itself was evaluated. You can fix it this way:

this.selectedItem.image = this.selectedItem.image || {}
image = this.selectedItem.image.url || null;

TypeScript:

image = this?.selectedItem?.image?.url || null;

本文标签: javascripttype error and shortcircuit evaluationStack Overflow