Object is possibly 'undefined' error in TypeScript [Solved]

avatar
Borislav Hadzhiev

Last updated: Feb 27, 2024
5 min

banner

# Object is possibly 'undefined' error in TypeScript

The "Object is possibly 'undefined'" error occurs when we try to access a property on an object that may be undefined (e.g. marked as optional).

To solve the error, use optional chaining to short-circuit if the reference is equal to null, e.g. p1?.address?.country.

object is possibly undefined

Here is an example of how the error occurs.

index.ts
type Person = { address?: { // ๐Ÿ‘ˆ๏ธ could be undefined country?: string; city?: string; }; }; const p1: Person = {}; // โ›”๏ธ Error: Object is possibly 'undefined'.ts(2532) p1.address.country;

ts object is possibly undefined

The address property on the Person type is marked as optional, so it might be undefined.

This is why we aren't able to safely access the country or city properties.

# Using the optional chaining (?.) operator

You can use the optional chaining (?.) operator to resolve the issue.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = {}; // โœ… No error const result = p1?.address?.country; console.log(result); // ๐Ÿ‘‰๏ธ undefined

using optional chaining operator to solve the error

The code for this article is available on GitHub

The question mark dot (?.) syntax is called optional chaining in TypeScript.

It is like using dot notation to access a nested property of an object but instead of throwing an error if the reference is nullish (null or undefined), it short-circuits returning undefined.

This approach is commonly used when fetching data from a remote API or reading data from a file where some of the properties might not have a value.

# Providing a fallback value if the property doesn't exist

You can combine the optional chaining (?.) operator with the nullish coalescing (??) operator to specify a default value if the property doesn't exist.

index.ts
type Person = { address?: { // ๐Ÿ‘ˆ๏ธ could be undefined country?: string; city?: string; }; }; const p1: Person = {}; const result = p1?.address?.country ?? 'fallback value'; console.log(result); // ๐Ÿ‘‰๏ธ fallback value

providing fallback value if property does not exist

The code for this article is available on GitHub

If the value to the left of the nullish coalescing operator (??) is equal to null or undefined, the value to the right is returned, otherwise, the value to the left of the operator is returned.

If trying to access the nested country property on the object returns undefined, then the value to the right of the nullish coalescing (??) operator is returned.

# Using an if statement to solve the error

An alternative approach is to use a simple if statement as a type guard.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = {}; if (p1.address != undefined) { console.log(p1.address.country?.toUpperCase); console.log(p1.address.city?.toUpperCase); }

using if statement to solve the error

The code for this article is available on GitHub

We used an if statement to check if the p1.address property is not equal to undefined or null.

Once we enter the if block, TypeScript knows that the p1.address property is of type object, and not undefined.

Notice that we used the loose inequality (!=) operator, which checks for both undefined and null. You can exclusively check for undefined with strict not equals (!==).

The loose comparison covers both undefined and null, because in a loose comparison undefined is equal to null.

index.ts
console.log(undefined == null); // ๐Ÿ‘‰๏ธ true console.log(undefined === null); // ๐Ÿ‘‰๏ธ false

# Using the non-null assertion operator to solve the error

If you are sure the property cannot possibly have a null value, you can use the non-null assertion operator.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = { address: { country: 'Chile', city: 'Santiago', }, }; console.log(p1.address!.country); // ๐Ÿ‘‰๏ธ "Chile" console.log(p1.address!.city); // ๐Ÿ‘‰๏ธ "Santiago"

using non null assertion operator to solve the error

The code for this article is available on GitHub

The exclamation mark is the non-null assertion operator in TypeScript.

It removes 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 p1.address will never have a value of null or undefined.

# Solve the error using the logical AND (&&) operator

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.

index.ts
type Person = { address?: { country?: string; city?: string; num?: number; }; }; const p1: Person = {}; if ( p1?.address && typeof p1.address.num === 'number' && p1.address.num > 10 ) { console.log('success'); }
The code for this article is available on GitHub

The logical AND (&&) operator makes sure the address property isn't undefined, that num exists on the object and is a number before comparing it to the number 10.

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:

index.ts
type Person = { address?: { country?: string; city?: string; num?: number; }; }; const p1: Person = {}; // โ›”๏ธ Error: Object is possibly 'undefined'.ts(2532) if (p1?.address?.num > 10) { console.log('success'); }

The result might have a value of undefined because that's the return value of the optional chaining (?.) operator when it short-circuits.

The num property might have a value of undefined, so we can't directly compare it to a number.

Another common way to avoid getting the error is to use the logical AND (&&) operator.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = {}; if (p1.address && p1.address.country) { // ๐Ÿ‘‡๏ธ const result: string const result = p1.address.country; }
The logical AND (&&) operator won't evaluate the value to the right if the value to the left is falsy (e.g undefined).

All the values in the if condition have to be truthy for the if block to run.

The falsy values in JavaScript are: undefined, null, false, 0, "" (empty string), NaN (not a number).

All other values are truthy.

This is why TypeScript is able to infer the type of the result variable to be string in the if block.

# Using the typeof operator to solve the error

An even better way to get around the error in this situation is to use the typeof operator.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = {}; if (p1.address && typeof p1.address.country === 'string') { // ๐Ÿ‘‡๏ธ const result: string const result = p1.address.country; }
The code for this article is available on GitHub

We explicitly check if the type of the country 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 the typeof operator is better.

index.ts
type Person = { address?: { country?: string; city?: string; }; }; const p1: Person = { address: { country: '' } }; if (p1.address && p1.address.country) { // โ›”๏ธ This doesn't run const result = p1.address.country; console.log(result); } else { // ๐Ÿ‘‡๏ธ this block runs console.log('โœ… this runs'); }

This else block runs in the example above.

The country 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. It helps us avoid some difficult-to-spot bugs.

# Conclusion

The "Object is possibly 'undefined'" error occurs when we try to access a property on an object that may have a value of undefined.

To solve the error, use the optional chaining operator or a type guard to make sure the reference is not undefined before accessing properties.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev