Last updated: Feb 27, 2024
Reading time·4 min

To check if a property exists in an object in TypeScript:
undefined, it exists in the object.type Employee = { name?: string; department?: string; country?: string; }; const emp: Employee = {}; // ✅ Explicitly checking if (emp.department !== undefined) { console.log(emp.department.toLowerCase()); // now string } // ✅ Using optional chaining console.log(emp.department?.toLowerCase());

Note that we used a question mark to set the properties in the Employee type
to
optional.
undefined, or a value of type string.If you don't have all of the property names in the object in advance, use an index signature.
type Employee = { [key: string]: string; }; const emp: Employee = {}; // ✅ Explicitly checking if (emp.department !== undefined) { console.log(emp.department.toLowerCase()); // now string } // ✅ Using optional chaining console.log(emp.department?.toLowerCase());

The {[key: string]: string} syntax is an index signature and is used when we
don't know all of the object's properties ahead of time, but know the shape of
the values.
In either scenario, you can only check if a property exists in a TypeScript object if the property is compatible with the object's type.
type Employee = { name?: string; department?: string; country?: string; }; const emp: Employee = {}; // ⛔️ Property 'randomkey' does not exist on type 'Employee'. if (emp.randomkey !== undefined) { }
The Employee type doesn't have a randomkey property, so we aren't able to
check if it exists in the object.
undefinedThe best way to check for a key's existence in TypeScript is to explicitly check
if accessing the specific key in the object returns a value of undefined.
type Employee = { name?: string; department?: string; country?: string; }; const emp: Employee = {}; // 👇️ (property) department?: string | undefined emp.department // ✅ Explicitly checking if (emp.department !== undefined) { console.log(emp.department.toLowerCase()); }

The department property has a type of string or undefined because it's
marked as optional.
However, in the if statement, its type is string. This is called a
type guard in TypeScript.
We can use any string-specific built-in methods in the if statement because
TypeScript knows that if the department property isn't undefined, then it is
a string.
if statement wouldn't run if the property is explicitly set to undefined in the object.Alternatively, you can use optional chaining (?.).
You can also use the optional chaining (?.) operator to check if a property exists in an object.
type Employee = { address?: { country?: string; city?: string; }; }; const emp: Employee = {}; // ✅ Using optional chaining console.log(emp.address?.country?.toLowerCase()); console.log(emp.address?.city?.toLowerCase()); if (emp.address?.country !== undefined) { // ✅ Now emp.address.country is string console.log(emp.address.country.toLowerCase()); }

If the property exists in the object, the optional chaining (?.) operator will
return the corresponding value, otherwise, the operator short-circuits returning
undefined.
You can also use this approach to check for the existence of deeply nested properties in an object.
I've also written an article on how to get an object's key by value in TS.
in and hasOwnPropertyYou might see examples online that use the in operator or the hasOwnProperty
method to check for a key's existence in an object.
type Employee = { name?: string; department?: string; country?: string; }; const emp: Employee = {}; if ('department' in emp) { // 👇️ (property) department?: string | undefined console.log(emp.department); } if (emp.hasOwnProperty('department')) { // 👇️ (property) department?: string | undefined console.log(emp.department); }
The
in operator
returns true if the specified key is in the object or its prototype chain.
However, note that the type of the department property in the if block is
still string | undefined.
department key in the object to have a value of undefined.This would work in a different way if you use an index signature like
{[key: string]: string}.
type Employee = { [key: string]: string; }; const emp: Employee = {}; if ('department' in emp) { // 👇️ emp.department is string console.log(emp.department); } if (emp.hasOwnProperty('department')) { // 👇️ emp.department is string console.log(emp.department); }
The index signature {[key: string]: string} means that when the object is
indexed with a string key, it will always return a value of type string.
This is why the in operator and the hasOwnProperty method are able to serve
as type guards and determine the type of the department property to be a
string in the if statements.
The
hasOwnProperty
method is different from the in operator because it checks if the property
exists directly on the object (excluding its prototype chain).
type Employee = { [key: string]: string; }; const emp: Employee = {}; if (emp.hasOwnProperty('department')) { // 👇️ emp.department is string console.log(emp.department); }
If ESLint is giving you an error, you can get around it by calling the method on
the Object.prototype.
type Employee = { [key: string]: string; }; const emp: Employee = {}; if (Object.prototype.hasOwnProperty.call(emp, 'department')) { // 👇️ emp.department is string console.log(emp.department); }
Which approach you pick is a matter of personal preference. I'd go with
explicitly checking if accessing the property in the object returns a value of
undefined as it is the easiest to read and the most explicit approach.