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: