Incompatibility with jest-mock-extended

Author: eyalrothCreated Aug 10, 2025Updated Nov 27, 2025

Bug description

Trying to mergeDeep with mocks from jest-mock-extended leads to strange behavior:

typescript
import { mergeDeep } from 'immutable';
import { mock } from 'jest-mock-extended';

describe('immutable + jest-mock-extended', () => {

  test('mergeDeep', () => {
    const myMock = mock();

    const merged = mergeDeep({ myMock }, { myMock });

    console.log(merged.myMock); // undefined!

    expect(merged.myMock).toBe(myMock); // fails because merged.myMock is undefined
  });
});

Cause

It seems that the various isImmutable functions (e.g isCollection) make their assertion on "symbols" like so:

typescript
function isImmutable(obj) {
  return new Boolean(obj && obj[SYMBOL]);
}

The problem is with the obj[SYMBOL] assertion, which will return true for any truthy value, and not necessarily what the package set as value (a literal true).

Now, the mocks from jest-mock-extended seem to return a Proxy that, if a key on the object is accessed, the proxy populates that key with a function (which is truthy):

typescript
  test('isImmutable', () => {
    const myMock = mock();
    isImmutable(myMock); 
    console.log(myMock); // it now has `'@@__IMMUTABLE_ITERABLE__@@': [Function: mockConstructor] { ... }` property
  });

This makes the package think that the original values (the mocks) given to mergeDeep originated from the package, which likely messes up with its logic. I'm assuming this will affect other methods as well.

Potential solutions

  1. Perform a more strict check on the value of the "symbol" (=== true or even === SOME_UNIQUE_SYMBOL).
  2. Change the symbol check to obj.hasOwnProperty(SYMBOL), which will not "trigger" the auto population of the mock proxy.

Source: immutable-js/immutable-js