Skip to content Skip to sidebar Skip to footer

Immutable.fromjs() Is Not Deep

The description of Immutable.fromJS is: Deeply converts plain JS objects and arrays to Immutable Maps and Lists. But that's wrong. I have an object with the following structure.

Solution 1:

The very first sentence in the docs for fromJS is:

Deeply converts plain JS objects and arrays to Immutable Maps and Lists.

If Foo, Bar, and Baz are ES6 classes then they are neither plain JS objects nor arrays—they're instances of a class. So, no, the docs are not incorrect.

As an aside, if Immutable.fromJS automatically converted any object it encountered into a plain JS object, as you seem to have expected it to, that would be very surprising behavior to most users, and not at all desirable.

But since that's the behavior you want, you'll be happy to know that the Immutable wiki has a section on this exact topic, which I'll duplicate here for posterity:

Here is an example which will convert any Object, including exotic Objects, to Immutable.Map:

function fromJSGreedy(js) {
  return typeof js !== 'object' || js === null ? js :
    Array.isArray(js) ? 
      Immutable.Seq(js).map(fromJSGreedy).toList() :
      Immutable.Seq(js).map(fromJSGreedy).toMap();
}

That's pretty simple. And, indeed, it works exactly as promised, as you can see by running the below snippet.

classFoo {
  constructor(name, ...children) {
    this.name = name;
    this.children = children;
  }
}

classBarextendsFoo {}
classBazextendsFoo {}

const myBar = newBar("myBar", newBaz("myBaz1"), newBaz("myBaz2"));
const myFoo = newFoo("myFoo", myBar);

functionfromJSGreedy(js) {
  returntypeof js !== 'object' || js === null ? js :
    Array.isArray(js) ? 
      Immutable.Seq(js).map(fromJSGreedy).toList() :
      Immutable.Seq(js).map(fromJSGreedy).toMap();
}

console.log(fromJSGreedy(myFoo).toString());
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

Solution 2:

Additionally, I had to check for Date types because this function was converting my dates into non-date objects. This function uses typescript and lodash, but I'm sure you can alter it accordingly

export function myFromJS(js: any): any {
  return typeof js !== 'object' || js === null || (_.isDate(js)) ? js :
    Array.isArray(js) ?
      Immutable.Seq(js).map(myFromJS).toList() :
      Immutable.Seq(js).map(myFromJS).toMap();
}

Post a Comment for "Immutable.fromjs() Is Not Deep"