Hone logo
Hone
Problems

Custom Jest Matcher: toBeInstanceOf

Jest's built-in matchers are powerful, but sometimes you need more specific checks. This challenge asks you to create a custom Jest matcher called toBeInstanceOf that verifies if a value is an instance of a specified class or constructor function. This is particularly useful when working with inheritance and ensuring objects are of the expected type.

Problem Description

You need to implement a custom Jest matcher named toBeInstanceOf. This matcher should take a constructor function (class or function) as an argument and return true if the value being tested is an instance of that constructor, and false otherwise. The matcher should work correctly with both classes and regular functions used as constructors.

Key Requirements:

  • The matcher must be named toBeInstanceOf.
  • It must accept a single argument: the constructor function (class or function).
  • It must use the instanceof operator to perform the type check.
  • It should provide a clear and informative failure message if the check fails.
  • It should handle cases where the constructor is null or undefined gracefully (returning false and providing a helpful message).
  • It should handle primitive values correctly (returning false).

Expected Behavior:

  • value.toBeInstanceOf(Constructor) should return true if value is an instance of Constructor.
  • value.toBeInstanceOf(Constructor) should return false if value is not an instance of Constructor.
  • The failure message should clearly indicate the expected type (the constructor) and the actual type of the value.

Edge Cases to Consider:

  • null or undefined constructor: Should return false and provide a descriptive error message.
  • Primitive values (string, number, boolean, symbol, etc.): Should return false.
  • Classes and functions used as constructors.
  • Inheritance: An instance of a subclass should also pass the toBeInstanceOf check for its parent class.

Examples

Example 1:

class Animal {}
class Dog extends Animal {}

const myDog = new Dog();
expect(myDog).toBeInstanceOf(Dog); // true
expect(myDog).toBeInstanceOf(Animal); // true (due to inheritance)
expect(myDog).toBeInstanceOf(Object); // false
expect("hello").toBeInstanceOf(Dog); // false

Explanation: myDog is an instance of Dog and Animal, so the matcher returns true in both cases. A string is not an instance of Dog, so the matcher returns false.

Example 2:

function MyFunc() {}
const myFuncInstance = new MyFunc();
expect(myFuncInstance).toBeInstanceOf(MyFunc); // true
expect(myFuncInstance).toBeInstanceOf(Function); // false

Explanation: myFuncInstance is an instance of MyFunc, but not of Function itself.

Example 3: (Edge Case)

class MyClass {}

expect(null).toBeInstanceOf(MyClass); // Error: Expected null not to be an instance of MyClass.
expect(undefined).toBeInstanceOf(MyClass); // Error: Expected undefined not to be an instance of MyClass.

Explanation: Passing null or undefined as the constructor should result in a clear error message.

Constraints

  • The matcher must be implemented in TypeScript.
  • The matcher should be compatible with Jest versions 25 or higher.
  • The matcher should not introduce any external dependencies.
  • The matcher should be performant; the instanceof operator is generally efficient.

Notes

  • Remember that Jest matchers are expected to have pass and message methods.
  • Consider how to provide a helpful error message when the check fails, including the expected and actual types.
  • Think about how to handle edge cases gracefully to prevent unexpected errors.
  • The instanceof operator can be tricky with cross-frame or cross-realm scenarios, but for this challenge, you can assume a standard JavaScript environment.
Loading editor...
typescript