Check if a Property exists in an Object in TypeScript

avatar

Borislav Hadzhiev

Mon Feb 28 20224 min read

Check if a Property exists in an Object in TypeScript #

To check if a property exists in an object in TypeScript:

  1. Mark the specific property as optional in the object's type.
  2. Use a type guard to check if the property exists in the object.
  3. If accessing the property in the object does not return a value of undefined, it exists in the object.
index.ts
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.

This means that the properties we marked as optional can either have a value of undefined in the object or a value of type string.

If you don't have all of the names of properties in the object in advance, you can use an index signature.

index.ts
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 in the example 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.

index.ts
type Employee = { name?: string; department?: string; country?: string; }; const emp: Employee = {}; // ⛔️ Property 'randomkey' does not // exist on type 'Employee'.ts(2339) if (emp.randomkey !== undefined) { }

The Employee type in the example does not have a randomkey property, so we aren't able to check if it exists in the object.

The 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.

index.ts
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, if the if statement, its type is string. This is called a type guard in TypeScript.

We are able to use any string-specific built-in methods in the if statement, because TypeScript knows that if the department property is not undefined, then it is a string.

Note that the if statement would not run if the property is explicitly set to undefined in the object.

Alternatively, you can use optional chaining.

Use optional chaining (?.) to check if a property exists in a TypeScript object, e.g. emp.myProperty?.toLowerCase(). If the property exists in the object, the optional chaining operator will return the properties value, otherwise it short-circuits returning undefined.

index.ts
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()); }

The optional chaining (?.) operator short-circuits if the reference is nullish (null or undefined) instead of throwing an error.

This is very convenient when you want to quickly check if a property exists in an object inline, e.g. to call a built-in method.

You can also use this approach to check for the existence of deeply nested properties in an object.

You might see examples online that use the in operator or the hasOwnProperty method to check for a key's existence in an object.

index.ts
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.

This is because we might have explicitly set the department key in the object to have a value of undefined.

This would work in a different way if you were using an index signature like {[key: string]: string}.

index.ts
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 key that is a string, it will always return a value of type string.

This is why the in operator and the hasOwnProperty methods 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).

index.ts
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.

index.ts
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.

Use the search field on my Home Page to filter through my more than 1,000 articles.