Resolving JavaScript TypeError: Cannot use ‘in’ operator to search for ‘X’ in ‘Y’


In the blogpost, we’ll learn several ways of avoiding the JavaScript TypeError: Cannot use 'in' operator to search for 'X' in 'Y'. First we’ll learn about the in operator, then we explore various techniques to avoid the TypeError associated with in. Then we see some common mistakes and lastly, solidify our understanding with a relevant practice question.

Lets dive in! 👨‍💻


Refresher: Understanding the JavaScript ‘in’ operator, and “TypeError: Cannot use ‘in’ operator to search…

The ‘in’ operator in JavaScript is used to check if a property exists within an object or its prototype chain. Unlike methods that check values (like Array.includes()), the ‘in’ operator is specifically about property names (which can be string or symbol types).

Particularly useful when you want to confirm the existence of a property without necessarily needing to know its value. It’s also commonly used in conditional statements to ensure that an operation involving a property is safe to execute.

But note that, in doesn’t not work with strings. You should rather use String.includes() or String.charAt(), as will be discussed in later sections.

In following examples, 'make' in car returns true because make is a property of the car object. In the array colors, 0 in colors returns true as there is an element at index 0. As warned that we can’t use in with Strings, so looking for either index or character in string will throw the TypeError: Cannot use ‘in’ operator to search for ‘X’ in ‘Y’.

Now that we know how to get this error, lets see multiple ways to avoid it.

Modulo operator (JavaScript)
// Using 'in' with an object
const car = {
    make: 'Toyota',
    model: 'Corolla'
};
console.log('make' in car);  // true
console.log('year' in car);  // false

// Using 'in' with an array
const colors = ['red', 'green', 'blue'];
console.log(0 in colors); // true
console.log(3 in colors); // false

// ⚠ But don't use `in` with Strings. Some bad examples below:

const greeting = "Hello";
console.log(("H" in greeting)); 
// TypeError: Cannot use 'in' operator to search for 'H' in Hello
// . . . (and quite a StackTrace!🥴)

console.log((0 in greeting));// Again same error: 🥴
// TypeError: Cannot use 'in' operator to search for '0' in Hello 

Ways to avoid “TypeError: Cannot use ‘in’ operator to search for ‘X’ in ‘Y’

Use type checking with typeof with JavaScript ‘in’ operator

Before using the ‘in’ operator, it’s important to ensure that the operand on its right-hand side is an object (or can be treated as an object, like an array). JavaScript is dynamically typed, meaning variables can hold values of different types, and their types can change. Using typeof is a way to safeguard against applying ‘in’ to a non-object, which would result in a TypeError.

  • In following example, typeof is used to check if person and personArray are objects before applying the ‘in’ operator. This prevents a possible TypeError if ‘in’ were used on a string like personName. Note, in JavaScript, the typeof array is an object.
Type Checking with typeof (JavaScript)
const person = { name: "Alice" };
const personName = "Alice";
const personArray = ["Alice"];

// Correct use
if (typeof person === "object" && person !== null) {
  console.log("name" in person); // true
}

// Incorrect use, would throw a TypeError
// console.log('name' in personName);

// Correct use with an array
if (
  typeof personArray === "object" &&
  personArray !== null
) {
  console.log(0 in personArray); // true
}

Using Object.hasOwnProperty() Method instead of JavaScript ‘in’ operator

While the ‘in’ operator checks for the existence of a property in an object and its prototype chain, Object.hasOwnProperty() method is used to check if an object has a property as its own (not inherited from its prototype). This is considered a safer and more precise way to check for property existence, especially when you want to ignore properties inherited from the prototype.

This method is particularly useful in situations where you only care about the properties that are directly on the object, not those inherited through its prototype. It is a crucial method in JavaScript when dealing with objects where the distinction between own properties and inherited properties matters.

  • In following example, myCar.hasOwnProperty('make') returns true because make is an own property of myCar.
  • However, myCar.hasOwnProperty('year') returns false as year is a property inherited from the Car prototype, not an own property of the myCar instance.
  • This distinction is crucial for certain operations where inherited properties might lead to unexpected behavior or need to be filtered out.
Using Object.hasOwnProperty() Method (JavaScript)
function Car(make, model) {
    this.make = make;
    this.model = model;
}

Car.prototype.year = 2020;

const myCar = new Car('Toyota', 'Corolla');

console.log(myCar.hasOwnProperty('make'));  
// true

console.log(myCar.hasOwnProperty('year'));  
// false, because 'year' is inherited

Ensuring Non-null Values with JavaScript ‘in’ operator

In JavaScript, it’s crucial to ensure that the value you are working with is not null or undefined before using the ‘in’ operator. This is because the ‘in’ operator will throw a TypeError if it is used on values that are null or undefined. Therefore, it’s a common and necessary practice to check for these values beforehand to ensure the code runs without errors.

Ensuring Non-null Values (JavaScript)
const person = { name: 'Alice', age: 25 };
let undefinedPerson;

// Correct usage with a null check
if (person && 'name' in person) {
    console.log("Name exists in person");
}

// Incorrect usage, would throw a TypeError
// if ('name' in undefinedPerson) {
//     console.log("This will not execute");
// }

// Using logical AND (&&) operator for null check
if (undefinedPerson && 'name' in undefinedPerson) {
    console.log("This will not execute");
} else {
    console.log("undefinedPerson is null or undefined");
}

Parsing JSON Strings before using JavaScript ‘in’ operator

When working with JSON data in JavaScript, it’s common to receive data as a JSON string. To use the ‘in’ operator with this data, you first need to parse the JSON string into a JavaScript object. This conversion is necessary because the ‘in’ operator works with objects (or arrays), not with string representations of them.

Parsing JSON Strings (JavaScript)
const jsonStr = '{"name": "Alice", "age": 25}';
const parsedObj = JSON.parse(jsonStr);

console.log('name' in parsedObj);  // true
console.log('address' in parsedObj);  // false

Using includes() for Strings and Arrays, instead of JavaScript ‘in’ operator

The includes() method is used in JavaScript for strings and arrays to check if they contain a specific substring or element, respectively. It’s a more appropriate choice than the ‘in’ operator for these types of checks, as ‘in’ is intended for property names in objects or indices in arrays.

Using includes() for Strings and Arrays (JavaScript)
// For Strings
const greeting = "Hello, world!";
console.log(greeting.includes("world")); // true
console.log(greeting.includes("bye")); // false

// For Arrays
const fruits = ['apple', 'banana', 'mango'];
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('orange')); // false

Using JavaScript ‘in’ operator with Arrays correctly

The ‘in’ operator can be used with arrays to check if certain indices exist. It’s important to understand that ‘in’ checks for the presence of indices (i.e., keys) in an array, not the array’s values. This can be particularly useful when dealing with sparse arrays, where certain indices might not be populated.

In following example, 0 in colors, 2 in colors, and 3 in colors return true because these indices exist in the array colors, even though the value at index 2 is undefined. On the other hand, 4 in colors returns false because there is no element at index 4. This demonstrates that ‘in’ is checking for the existence of indices, not the values held at those indices.

‘in’ with Arrays (JavaScript)
const colors = ['red', 'green', undefined, 'blue'];

console.log(0 in colors); // true - 'red' is at index 0
console.log(2 in colors); // true - there is an undefined value at index 2
console.log(3 in colors); // true - 'blue' is at index 3
console.log(4 in colors); // false - no element at index 4

Using Array.prototype.some(), indexOf(), or find() instead of JavaScript ‘in’ operator

In JavaScript, Array.prototype.some(), indexOf(), and find() are methods used for searching elements within an array. Each method serves a slightly different purpose:

  • some(): Tests whether at least one element in the array passes the test implemented by the provided function. It returns a boolean.
  • indexOf(): Provides the first index at which a given element can be found in the array, or -1 if it is not present.
  • find(): Returns the value of the first element in the array that satisfies the provided testing function. If no elements satisfy the testing function, undefined is returned.
some(), indexOf(), or find() (JavaScript)
const numbers = [1, 2, 3, 4, 5];

// Using some()
const hasEvenNumber = numbers.some(num => num % 2 === 0);
console.log(hasEvenNumber); // true

// Using indexOf()
const indexThree = numbers.indexOf(3);
console.log(indexThree); // 2

// Using find()
const firstEven = numbers.find(num => num % 2 === 0);
console.log(firstEven); // 2

Refactoring to avoid JavaScript ‘in’ Operator

Refactoring code to avoid using the ‘in’ operator can be more efficient, especially with arrays. Since ‘in’ checks for the presence of indices and not values, using array-specific methods like includes(), some(), or find() can often be more intuitive and prevent misunderstandings.

Refactoring to avoid `in` (JavaScript)
const fruits = ['apple', 'banana', 'mango'];

// Initial use of 'in' (not recommended for arrays)
let isBananaIndex = 1 in fruits; // true, but not clear

// Refactored to use 'includes()'
let hasBanana = fruits.includes('banana');
console.log(hasBanana); // true

Using Object.keys() or Object.entries()

Object.keys() and Object.entries() are methods used for object inspection in JavaScript. They provide a way to access the keys or entries (key-value pairs) of an object, which can be especially useful for iterating over an object or checking its properties.

  • Object.keys(): Returns an array of a given object’s property names (keys).
  • Object.entries(): Returns an array of a given object’s own enumerable string-keyed property [key, value] pairs.

These methods are particularly useful when you need a more detailed inspection of an object, especially to avoid TypeErrors with the ‘in’ operator in scenarios where the object structure is dynamic or unknown.

Using Object.keys() or Object.entries() (JavaScript)
const car = {
    make: 'Toyota',
    model: 'Corolla',
    year: 2020
};

// Using Object.keys()
const keys = Object.keys(car);
console.log(keys); // ['make', 'model', 'year']

// Using Object.entries()
const entries = Object.entries(car);
for (const [key, value] of entries) {
    console.log(`${key}: ${value}`);
    // Outputs: make: Toyota, model: Corolla, year: 2020
}

Tips & errors while using JavaScript ‘in’ operator

Checking for Null or Undefined Before Using ‘in’

In JavaScript, attempting to access a property of null or undefined will throw a TypeError. This often happens when trying to use the ‘in’ operator, some(), find(), or Object.keys() on variables that might not be properly initialized.

Checking for Null or Undefined Before Using ‘in’ (JavaScript)
let person = null;
// Incorrect approach that leads to TypeError
// if ('name' in person) {...}

// Correct approach
if (person !== null && person !== undefined && 'name' in person) {
    console.log('Name property exists.');
} 
// Equivalent to above if check.
// else if(persone && 'name' in person) {
//     console.log('Name property exists.');
// }
else {
    console.log('Person is either null or undefined.');
}

Don’t confuse Properties with Values

Properties are the keys of an object (like ‘name’ in a person object), whereas values are the elements of an array or characters in a string. Using ‘in’ for arrays or strings can lead to confusion since it checks for indices or properties, not the actual values or characters.

Remember, ‘in’ is for property names (keys) in objects, while includes() is for values in arrays or strings.

Don’t confuse Properties with Values (JavaScript)
const person = { name: 'Alice', age: 30 };
const fruits = ['apple', 'banana'];

// Correct approach for object properties
console.log('name' in person); // true

// Incorrect for array values; 'banana' is a value, not an index
console.log('banana' in fruits); // false

// Correct approach for array values
console.log(fruits.includes('banana')); // true

Don’t misuse ‘in’ with Arrays

The ‘in’ operator checks whether an index exists in an array. It does not check for the presence of a value. This is a common source of confusion, as using ‘in’ to check for values can lead to unexpected results.

Don’t misuse ‘in’ with Arrays (JavaScript)
const colors = ['red', 'green', 'blue'];

// Checking for the existence of an index
console.log(1 in colors); // true - 'green' exists at index 1

// Incorrectly checking for a value
console.log('red' in colors); // false

// Correct approach for values
console.log(colors.indexOf('red') !== -1); // true

Note case sensitivity in methods like includes()

JavaScript string comparisons, including methods like includes(), indexOf(), and startsWith(), are case-sensitive. This can lead to missed matches if the case isn’t considered.

Case sensitivity (JavaScript)
const sentence = "The Quick Brown Fox";

// Case-sensitive check
console.log(sentence.includes("quick")); // false

// Case-insensitive check
console.log(sentence.toLowerCase().includes("quick")); // true

// Another example with indexOf()
console.log(sentence.indexOf("Brown") !== -1); // true
console.log(sentence.toLowerCase().indexOf("brown") !== -1); // true

Not overlook JavaScript’s dynamic typing

JavaScript’s dynamic typing means that the type of a variable can change. Mistaken assumptions about a variable’s current type can lead to bugs and errors.

Use typeof or Array.isArray() to check types, and be cautious with type coercion.

Dynamic typing (JavaScript)
let item = "123";
let count = 123;

// Type checking
if (typeof item === 'string') {
    console.log('Item is a string.');
}

// Potential type confusion
if (item == count) { // Loose equality
    console.log('Item and count are loosely equal.');
}

// Avoiding type coercion
if (item === count.toString()) {
    console.log('Item and count are strictly equal as strings.');
}

Correctly use of Object.hasOwnProperty()

Object.hasOwnProperty() checks if a property is directly on the object, not in its prototype chain. However, this method can be shadowed or overridden, leading to incorrect results.

Overridable Object.hasOwnProperty() (JavaScript)
const obj = {
    prop: 'exists',
    hasOwnProperty: function() {
        return false;
    }
};

// Incorrect: Method is shadowed
console.log(obj.hasOwnProperty('prop')); // false

// Correct: Using call to bypass shadowing
console.log(Object.hasOwnProperty.call(obj, 'prop')); // true

Don’t ignore undefined in Array Methods like find() or some()

When using array methods like find() or some(), undefined elements in the array are treated as valid elements. This can be problematic if you are not expecting undefined values.

undefined in Array Methods (JavaScript)
const mix = [1, undefined, 3, null];

// find() returns the first element that satisfies the condition
const firstUndefined = mix.find(element => element === undefined);
console.log(firstUndefined); // undefined

// some() checks if any element satisfies the condition
const hasUndefined = mix.some(element => element === undefined);
console.log(hasUndefined); // true

Not misinterpret indexOf() with Not Found (-1)

The indexOf() method returns -1 if the element is not found in the array. However, because -1 is a truthy value, it can lead to incorrect interpretations in conditional statements.

indexOf() vs Not Found (-1) (JavaScript)
const pets = ['cat', 'dog'];

// Correct way to check for non-existence
if (pets.indexOf('bird') === -1) {
    console.log('Bird is not a pet.');
}

// Incorrect way that leads to confusion
if (pets.indexOf('bird')) {
    // This won't execute because indexOf returns -1, which is truthy
}

Object.keys() and Object.entries() skips Prototype Properties

Object.keys() and Object.entries() only list an object’s own properties, not properties inherited from its prototype. This can be misleading if you’re expecting to see inherited properties as well.

Object.keys() and Object.entries() skips Prototype Properties (JavaScript)
function Person(name) {
    this.name = name;
}
Person.prototype.age = 30;

const alice = new Person('Alice');

// Only own properties are listed
console.log(Object.keys(alice)); // ['name']
console.log(Object.entries(alice)); // [['name', 'Alice']]

// Inherited properties are not included
console.log('age' in alice); // true
console.log(alice.hasOwnProperty('age')); // false

🧪Practice Coding Problem: Does Key Exist

Your turn now!😃 Lets test our understanding by solving a problem.

Write a function named doesKeyExist that checks if a key exists in an object or if an element exists in an array. This function should accomplish this without using the ‘in’ operator

Problem (JavaScript)
function doesKeyExist(key, collection) {
  // > > > 👉 Write code here 👈 < < <
}

// With Object
const person = { name: 'Alice', age: 25 };
console.log(doesKeyExist('name', person)); // true
console.log(doesKeyExist('gender', person)); // false

// With Array
const fruits = ['apple', 'banana', 'mango'];
console.log(doesKeyExist('banana', fruits)); // true
console.log(doesKeyExist('orange', fruits)); // false
Please attempt before seeing the Answer:
JavaScript
function doesKeyExist(key, collection) {
    if (Array.isArray(collection)) {
        // For arrays, use indexOf to check if the element exists
        return collection.indexOf(key) !== -1;
    } else if (typeof collection === 'object' && collection !== null) {
        // For objects, use hasOwnProperty to check if the key exists
        return Object.hasOwnProperty.call(collection, key);
    }
    return false; // Return false for non-object, non-array collections
}

Explanation:

  • Array Check: First, the function checks if collection is an array using Array.isArray(collection). If it is an array, the function uses indexOf to find if key exists as an element in the array. indexOf returns the first index at which a given element can be found in the array, or -1 if it is not present. Checking if the return value is not equal to -1 (!== -1) confirms the presence of the element.
  • Object Check: If collection is not an array, the function then checks if it is an object and not null (since typeof null is "object" in JavaScript). For objects, Object.hasOwnProperty.call(collection, key) is used to check if the key exists as a property of the object. This approach is used instead of collection.hasOwnProperty(key) to avoid issues if the hasOwnProperty method has been overridden or shadowed in collection.
  • Return Value: The function returns true if the key (or element) is found in the collection and false otherwise.

Now you an expert at correctly using the in operator (or even skip using), and avoid the JavaScript TypeError: Cannot use 'in' operator to search for....

Keep learning, and keep coding! 🚀👨‍💻

Scroll to Top