91

I'm trying to use the Typescript optional chaining operator but it threw this exception:

index.ts:6:1 - error TS2779: The left-hand side of an assignment
expression may not be an optional property access.

My sample code:

const url = URI({
    protocol: 'http',
    hostname: 'example.org' 
})

// This line threw
document.getElementById('output')?.innerHTML = url.toString()

How to resolve this problem?

7 Answers 7

139
objectVariableName!.propertyName = 'some value to assign';

Please note the exclamation symbol i.e,!

Sign up to request clarification or add additional context in comments.

6 Comments

How is this called? is this a ECMAScript implementation?
@Dazag Looks like it's a non-null assertion operator typescriptlang.org/docs/handbook/release-notes/…
This is a great answer. Helps the code readability. Thanks you
this is good only if you are sure that objectVariableName exists, you basically teling the compiler not to worry about this being undefined. but if it is undefined you will get an error
The alternative is to use the "if (objectVariableName) objectVariableName.propertyName = value" OR "objectVariableName && (objectVariableName.propertyName = value)". The non-null assertion operator will get you into trouble.
|
52
const output = document.getElementById('output');
if (output) output.innerHTML = url.toString()

This operator is made for accessing deep nest values.

Let's look at document.getElementById('output')?.innerHTML. This will return undefined (if '#output' not exists) or string (if '#output' exists). And you trying to assign string to it.

Here you are trying to set a new value for an object property that may not exist.

So yep, optional property access can not be used at the left-hand side of an assignment.

You can read more about it in proposal

2 Comments

I don't think the types are the issue here, as you can certainly assign a value of type string to a writable variable or property of type string | undefined. The issue is that foo?.bar is not writable at all, as it's equivalent to foo == null ? undefined : foo.bar, which you can't write to, even with undefined.
@jcalz, yep, sure, I was just tried to explain somehow, that here we are trying assign value to property of some object, that may be not exists. updated
5

in ES12 you can do this with Logical nullish assignment

document.getElementById('output')?.innerHTML ??= url.toString()

so the assignment will happen only if the left-hand expression is not nullish.

this is just like if you would do

if (document.getElementById('output')?.innerHTML) {
  document.getElementById('output').innerHTML = url.toString()
}

3 Comments

This is not true, the assignment will happen only if the left-hand expression is nullish. see tc39.es/ecma262/multipage/…
Did you mean to use if (document.getElementById('output')) {...}
You got it completely wrong. foo ??= val is the same as foo = foo ?? val, not what you're saying.
3

This very short expression works for me nicely in typescript 4.0.3

let domEl: HTMLElement | null = document.querySelector("#app");
domEl && (domEl.style.color = "green");

1 Comment

Many linters will complain about the fact that you're throwing away the result of the evaluation of domEl && (domEl.style.color = "green").
3

You can also solve this with an early return:

const output = document.getElementById('output');
if (!output) return;

output.innerHTML = url.toString()

Use it like this for nested properties:

if (!item?.text) return;

item.text.text = action.payload.text;

https://medium.com/swlh/return-early-pattern-3d18a41bba8

https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement

Comments

2

As mentioned here:

The Document method getElementById() returns an Element object representing the element whose id property matches the specified string.

If we go and see what properties the Element base class contains, you will see innerHTML.

This means that it is sure that an instance of Element(the result of getElementById) will have an innerHTML property, which is why you're getting the error.

1 Comment

Actually, the error is about getElementById() possibly returning NO element if there are no elements with the passed ID. Nothing to do with what is after the ? (innerHTML)
0

My exception was :

The left-hand side of an assignment expression may not be optional property access.

I received this error in typescript "~4.6.2" and solved it like.

let headingDom : HTMLElement | null = document?.querySelector('h1');
if(headingDom) headingDom.textContent = 'Hello World';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.