Last updated: Feb 28, 2024
Reading timeยท4 min

The error "The left-hand side of an assignment expression may not be an optional property access" occurs when we try to use optional chaining (?.) to assign a property to an object.
To solve the error, use an if statement that serves as a type guard
instead.
Here is an example of how the error occurs.
type Employee = { name: string; country: string; }; let employee: Employee | undefined; // ๐๏ธ could be undefined // โ๏ธ Error: The left-hand side of an // assignment expression may not be // an optional property access.ts(2779) employee?.country = 'Germany';

We aren't allowed to use the optional chaining (?.) operator on the left-hand side of an assignment.
if statement as a type guard to solve the errorTo solve the error, use an if statement as a
type guard before the assignment.
type Employee = { name: string; country: string; }; let employee: Employee | undefined; // ๐๏ธ could be undefined if (employee != undefined) { employee.country = 'Germany'; }

We used the loose not equals operator (!=), to check if the variable is NOT
equal to null and undefined.
This works because when compared loosely, null is equal to undefined.
console.log(null == undefined); // ๐๏ธ true console.log(null === undefined); // ๐๏ธ false
The if block is only run if employee doesn't store an undefined or a
null value.
This is similar to what the optional chaining (?.) operator does.
You might also see examples online that use the non-null assertion operator to solve the error.
type Employee = { name: string; country: string; }; const employee: Employee | undefined = { name: '', country: '' }; // ๐๏ธ could be undefined employee!.country = 'Germany';
The exclamation mark is the non-null assertion operator in TypeScript.
null and undefined from a type without doing any explicit type-checking.When you use this approach, you basically tell TypeScript that this value will
never be null or undefined.
null or undefined.Here is an example of using this approach to set a property on an object.
type Employee = { name: string; country: string; }; // ๐๏ธ could be undefined const employee: Employee | undefined = { name: '', country: '', }; employee!.country = 'Germany'; // ๐๏ธ { name: '', country: 'Germany' } console.log(employee);

In most cases, you should use a simple if statement that serves as a type
guard as we did in the previous code sample.
You can also use a type assertion to avoid getting the error. However, this isn't recommended.
type Employee = { name: string; country: string; }; // ๐๏ธ could be undefined const employee: Employee | undefined = { name: '', country: '', }; (employee as Employee).country = 'Germany'; // ๐๏ธ { name: '', country: 'Germany' } console.log(employee);

The (employee as Employee) syntax is called a type assertion.
Type assertions are used when we have information about the type of a value that TypeScript can't know about.
We effectively tell TypeScript that the employee variable will have a type of
Employee and not to worry about it.
This could go wrong if the variable is null or undefined as accessing a
property on a null or an undefined value would cause a runtime error.
You can also use the logical AND (&&) operator to avoid getting the error.
type Employee = { name: string; country: string; }; // ๐๏ธ could be undefined const employee: Employee | undefined = { name: '', country: '', }; employee && (employee.country = 'Germany'); console.log(employee); // ๐๏ธ { name: '', country: 'Germany' }

The logical AND (&&) operator checks if the value to the left is truthy before evaluating the statement in the parentheses.
If the employee variable stores a falsy value (e.g. null or undefined),
the code to the right of the logical AND (&&) operator won't run at all.
The falsy values in JavaScript are: false, undefined, null, 0, ""
(empty string), NaN (not a number).
All other values are truthy.
However, this approach can only be used to assign a single property at a time if
the value is not equal to null and undefined.
The optional chaining (?.) operator short-circuits if the reference is equal to
null or undefined.
type Employee = { name: string; country: string; }; let employee: Employee | undefined; // ๐๏ธ could be undefined // ๐๏ธ undefined console.log(employee?.country.toLowerCase());
The optional chaining (?.) operator will simply return undefined in the
example because employee has a value of undefined.
The purpose of the optional chaining (?.) operator is
accessing deeply nested properties
without erroring out if a value in the chain is equal to null or undefined.
However, the optional chaining operator cannot be used on the left-hand side of an assignment expression.
You can learn more about the related topics by checking out the following tutorials: