Problem

Write a function that checks if a given value is an instance of a given class or superclass. For this problem, an object is considered an instance of a given class if that object has access to that class’s methods.

There are no constraints on the data types that can be passed to the function. For example, the value or the class could be undefined.

Examples

Example 1

1
2
3
Input: func = () => checkIfInstanceOf(new Date(), Date)
Output: true
Explanation: The object returned by the Date constructor is, by definition, an instance of Date.

Example 2

1
2
3
4
5
6
7
8
Input: func = () => { class Animal {}; class Dog extends Animal {}; return checkIfInstanceOf(new Dog(), Animal); }
Output: true
Explanation:
class Animal {};
class Dog extends Animal {};
checkIfInstanceOf(new Dog(), Animal); // true

Dog is a subclass of Animal. Therefore, a Dog object is an instance of both Dog and Animal.

Example 3

1
2
3
Input: func = () => checkIfInstanceOf(Date, Date)
Output: false
Explanation: A date constructor cannot logically be an instance of itself.

Example 4

1
2
3
Input: func = () => checkIfInstanceOf(5, Number)
Output: true
Explanation: 5 is a Number. Note that the "instanceof" keyword would return false. However, it is still considered an instance of Number because it accesses the Number methods. For example "toFixed()".

Solution

Method 1 – Prototype Chain and Type Handling

Intuition

We need to check if a value is an instance of a class, including primitives like numbers and strings, which can access class methods via boxing. We must also handle edge cases like undefined and null.

Reasoning

For objects, we can use the instanceof operator. For primitives, we check if their constructor matches the class or if they can access the class’s prototype methods. Special care is needed for null and undefined, which are not instances of any class.

Approach

  1. If cls is not a function, return false.
  2. If val is null or undefined, return false.
  3. If val is an object or function, use instanceof to check.
  4. For primitives, check if their constructor matches cls or if cls.prototype is in their prototype chain.
  5. Return true if any check passes, else false.

Edge cases:

  • checkIfInstanceOf(5, Number) should return true.
  • checkIfInstanceOf(undefined, Number) should return false.
  • checkIfInstanceOf(Date, Date) should return false.

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function checkIfInstanceOf(val, cls) {
    if (typeof cls !== 'function') return false;
    if (val === null || val === undefined) return false;
    if (typeof val === 'object' || typeof val === 'function') {
        return val instanceof cls;
    }
    // For primitives, check constructor and prototype
    if (val?.constructor === cls) return true;
    try {
        return cls.prototype && Object.getPrototypeOf(val) === cls.prototype;
    } catch {
        return false;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function checkIfInstanceOf(val: any, cls: any): boolean {
    if (typeof cls !== 'function') return false;
    if (val === null || val === undefined) return false;
    if (typeof val === 'object' || typeof val === 'function') {
        return val instanceof cls;
    }
    if (val?.constructor === cls) return true;
    try {
        return cls.prototype && Object.getPrototypeOf(val) === cls.prototype;
    } catch {
        return false;
    }
}

Complexity

  • ⏰ Time complexity: O(1), as all checks are constant time operations.
  • 🧺 Space complexity: O(1), as no extra space is used beyond a few variables.