44

Immutable object can be an instance of:

  • Immutable.List
  • Immutable.Map
  • Immutable.OrderedMap
  • Immutable.Set
  • Immutable.OrderedSet
  • Immutable.Stack
Gajus
  • 55,791
  • 58
  • 236
  • 384
  • I am assuming there is a more user friendly approach than doing `instanceof` for every type. – Gajus Aug 09 '15 at 18:28

6 Answers6

42

There is an open ticket to improve the API which is on the roadmap for 4.0. Until this is implemented, I suggest you use Immutable.Iterable.isIterable() (docs).

Using instanceof is not reliable (e. g. returns false when different modules use different copies of Immutable.js)

Yves M.
  • 26,153
  • 20
  • 93
  • 125
mbh
  • 952
  • 9
  • 11
  • Assuming I don't have access to `Immutable` itself (only an instance of an object that I'd like to check, say in a 3rd party library) is using `item.asImmutable && item.asImmutable() === item` a reasonable proxy? This appears to work for `Immutable.Map/List` and feels more robust than `item.__proto__['@@__IMMUTABLE_MAP__@@']` – jamis0n Nov 05 '19 at 22:24
25

I have learned that using instanceof to determine wether object is Immutable is unsafe:

Module A:

var Immutable = require('immutable');
module.exports = Immutable.Map({foo: "bar});

Module B:

var Immutable = require('immutable');
var moduleA = require('moduleA');
moduleA instanceof Immutable.Map // will return false

Immutable.js API defines the following methods to check if object is an instance of Immutable:

and

The latter checks if:

True if an Iterable, or any of its subclasses.

List, Stack, Map, OrderedMap, Set and OrderedSet are all subclasses of Iterable.

Gajus
  • 55,791
  • 58
  • 236
  • 384
21

Immutable.js has isImmutable() function since v4.0.0-rc.1:

 import { isImmutable, Map, List, Stack } from 'immutable';

 isImmutable([]); // false
 isImmutable({}); // false
 isImmutable(Map()); // true
 isImmutable(List()); // true
 isImmutable(Stack()); // true
 isImmutable(Map().asMutable()); // false

If you use one of the previous versions, you can check if object is Immutable this way:

 Immutable.Iterable.isIterable(YOUR_ENTITY)

because all immutables inherit from the Iterable object

Anton Novik
  • 1,509
  • 1
  • 17
  • 29
  • 8
    This is not available in 3.8.1 – danday74 Jul 17 '17 at 14:32
  • 1
    Anyone knows how to view the API docs for the previous versions on their official website? – Romasato Oct 18 '17 at 10:18
  • 1
    @Romasato - Maybe not ideal, but I can view the documentation source for older versions on github, e.g. 3.8.2: https://github.com/facebook/immutable-js/blob/v3.8.2/type-definitions/Immutable.d.ts – killthrush Mar 16 '18 at 20:04
1

And this way you can get to know what type of Immutable Iterable variable is:

const obj0 = 'xxx';
const obj1 = Immutable.fromJS({x: 'XXX', z: 'ZZZ'});
const obj2 = Immutable.fromJS([ {x: 'XXX'}, {z: 'ZZZ'}]);

const types = ['List', 'Stack', 'Map', 'OrderedMap', 'Set', 'OrderedSet'];
const type0 = types.find(currType => Immutable[currType][`is${currType}`](obj0));
const type1 = types.find(currType => Immutable[currType][`is${currType}`](obj1));
const type2 = types.find(currType => Immutable[currType][`is${currType}`](obj2));

console.log(`Obj0 is: ${type0}`); // Obj0 is: undefined
console.log(`Obj1 is: ${type1}`); // Obj1 is: Map
console.log(`Obj2 is: ${type2}`); // Obj2 is: List
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>
webmato
  • 1,581
  • 1
  • 8
  • 6
0

Checking specific types will generally cause more work later on. Usually I would wait to lock types in by checking for Map or List, but...

My motivation here is mostly that my call .get of undefined poops itself really hard, and initializing properly all over the place helps, but doesn't catch all edge cases. I just want the data or undefined without any breakage. Specific type checking causes me to do more work later if I want it to make changes.

This looser version solves many more edge cases(most if not all extend type Iterable which has .get, and all data is eventually gotten) than a specific type check does(which usually only saves you when you try to update on the wrong type etc).

/* getValid: Checks for valid ImmutableJS type Iterable

    returns valid Iterable, valid Iterable child data, or undefined

    Iterable.isIterable(maybeIterable) && maybeIterable.get(['data', key], Map()), becomes
    getValid(maybeIterable, ['data', key], Map())

    But wait! There's more! As a result:
    getValid(maybeIterable) returns the maybeIterable or undefined 
    and we can still say getValid(maybeIterable, null, Map()) returns the maybeIterable or Map()            */

export const getValid = (maybeIterable, path, getInstead) =>
  Iterable.isIterable(maybeIterable) && path
    ? ((typeof path === 'object' && maybeIterable.getIn(path, getInstead)) || maybeIterable.get(path, getInstead))
    : Iterable.isIterable(maybeIterable) && maybeIterable || getInstead;


//Here is an untested version that a friend requested. It is slightly easier to grok.

export const getValid = (maybeIterable, path, getInstead) => {
  if(valid(maybeIterable)) {                 // Check if it is valid
    if(path) {                                        // Check if it has a key
      if(typeof path === 'object') {     // Check if it is an 'array'
        return maybeIterable.getIn(path, getInstead) // Get your stuff
      } else {
        maybeIterable.get(path, getInstead)          // Get your stuff
      }
    } else {
      return maybeIterable || getInstead;                 // No key? just return the valid Iterable
    }
  } else {
    return undefined;                       // Not valid, return undefined, perhaps should return false here
  }
}

Just give me what I am asking for or tell me no. Don't explode. I believe underscore does something similar also.

Urasquirrel
  • 1,025
  • 1
  • 13
  • 31
0

This may work in some cases:

typeof object.toJS === 'function'

You can use this ducktyping method if you check immutable vs plain objects (json), for example.

Dan K.K.
  • 4,999
  • 2
  • 26
  • 33