Borislav Hadzhiev
Thu Mar 24 2022·4 min read
Photo by Mitchell Orr
Updated - Thu Mar 24 2022
The "Object is possibly 'null' or 'undefined'" error occurs when we try to
access a property on an object that may have a value of null
or undefined
.
To solve the error, use optional chaining to short-circuit if the reference is
nullish, e.g. person?.address?.country
.
Here is an example of how the error occurs.
type Person = { address?: { // 👈️ may be null or undefined country?: string; city?: string; } | null; }; const person: Person = {}; // ⛔️ Error: Object is possibly 'null' or 'undefined'. console.log(person.address.country);
The address
property on the Person
type is marked as
optional
and can also be null
.
This is why we aren't able to safely access the country
or city
properties
on the object.
To get around this, we can use the optional chaining (?.) operator.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; // 👇️ const result: string | undefined const result = person?.address?.city;
The question mark dot (?.) syntax is called
optional chaining
in TypeScript and is like using dot notation to access a nested property of an
object, but instead of causing an error if the reference is nullish (null
or
undefined
), it short-circuits returning undefined
.
An alternative approach is to use a simple if
statement as a
type guard.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; // 👇️ checks for both null and undefined if (person.address != null) { console.log(person.address.country); console.log(person.address.city); }
We used an if
statement to check if the person.address
property is not equal
to null
or undefined
.
if
block, TypeScript knows that the address
property is an object, and not null
or undefined
.Notice that we used loose not equals (!=), which checks for both null
and
undefined
.
The loose comparison covers both null
and undefined
, because in a loose
comparison null
is equal to undefined
.
console.log(null == undefined); // 👉️ true console.log(null === undefined); // 👉️ false
If you are sure the property could not have a value of null
or undefined
,
you can use the non-null assertion operator.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = { address: { country: 'Austria', city: 'Linz', }, }; // 👇️ non-null assertion operator console.log(person.address!.city); // 👉️ "Austria" console.log(person.address!.country); // 👉️ "Linz"
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
.
We used it right after the address
property, so we are telling TypeScript that
person.address
will never have a value of null
or undefined
.
If you are making a comparison in an if
statement, use the logical AND (&&)
operator to make sure the property is of the correct type.
type Person = { address?: { country?: string; city?: string; streetNumber?: number; } | null; }; const person: Person = {}; if ( person?.address && typeof person.address.streetNumber === 'number' && person.address.streetNumber > 5 ) { console.log('success'); }
The logical AND (&&) operator makes sure the address
property is not null
or
undefined
and that the streetNumber
property exists on the object and is a
number
before comparing it to the number 5
.
This is needed, because if the reference is nullish (null
or undefined
), the
optional chaining operator (?.) will return undefined
and TypeScript doesn't
allow us to compare undefined
to a number
.
For example, this would fail:
type Person = { address?: { country?: string; city?: string; streetNumber?: number; } | null; }; const person: Person = {}; // ⛔️ cannot compare possibly undefined to number if (person?.address?.streetNumber > 5) { console.log('success'); }
undefined
, because that's the return value of the optional chaining operator (?.) when it short-circuits.The streetNumber
property might have a value of undefined
, so we can't
directly compare it to a number
.
Another common way to avoid getting the "Object is possibly null
or
undefined
" error is to use the
logical AND (&&)
operator.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; if (person.address && person.address.city) { // 👇️ const result: string const result = person.address.city; }
undefined
).If person.address
returns undefined
, then person.address.city
won't get
evaluated at all, so we won't get an error.
if
condition have to be truthy for the if
block to run.The truthy values are all values that are not falsy.
The falsy values in JavaScript are: null
, undefined
, false
, 0
, ""
(empty string), NaN
(not a number).
This is why TypeScript is able to infer the type of the result
variable to be
string
in the if
block.
An even better way to get around the "Object is possibly null
or undefined
"
error in this situation is to use the
typeof
operator.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = {}; if (person.address && typeof person.address.city === 'string') { // 👇️ const result: string const result = person.address.city; }
We explicitly check if the type of the city
property is a string. This is
better than checking if the value is truthy
because empty strings are falsy
values in JavaScript (and TypeScript).
Here is an example that illustrates why using typeof
is better.
type Person = { address?: { country?: string; city?: string; } | null; }; const person: Person = { address: { city: '' } }; if (person.address && person.address.city) { // 👉️ does NOT run console.log('⛔️ this does NOT run'); } else { // 👉️ else block runs console.log('✅ this runs'); }
The else
block runs in the example above.
city
property points to an empty string (falsy value), so just checking if the value is truthy might not be enough in your scenario.It's always better to be explicit and use the typeof
operator when possible,
because it helps us avoid some difficult to spot bugs.
The "Object is possibly null or undefined" error occurs when we try to access
a property on an object that may be null
or undefined
. To solve the error,
use the optional chaining operator or a type guard to make sure the reference is
not nullish before accessing properties.