Can I use destructuring assignment with immutable.js?

Tomas Kulich picture Tomas Kulich · Jan 13, 2016 · Viewed 7.4k times · Source

With standard JS objects, one can use destructuring assignment such as:

let obj = {name: 'james', code: '007'}
let {name, code} = obj // creates new variables 'name' and 'code' (with the proper values)

As suggested by some Flux / Redux evangelist, I use immutable.js for my app; can I use destructuring also on immutable List / Map? Of course, one could do:

let obj = immutable.fromJS({name: 'james', code: '007'})
let {name, code} = obj.toJS()

but this seems to have quite inefficient as the objects grow bigger (because the object needs to be deeply jsified first).

Answer

Tomas Kulich picture Tomas Kulich · Jan 13, 2016

With immutable List, the destructuring works quite straightforwardly. This is because destructuring of Arrays works on every iterable (Checking whether something is iterable) and is not subjected just to js Arrays.

With Map, the situation is more complicated. Unlike with List, the destructuring of Map-like structures IS subjected just to plain JS objects and nothing more. Currently, it does not seem that ES community considers this a good idea (see https://esdiscuss.org/topic/extensible-destructuring-proposal)

However, there exist babel-plugin that enables this: https://github.com/vacuumlabs/babel-plugin-extensible-destructuring Having this plugin installed and enabled in .babelrc, you can simply patch immutable Map to have a .@@get method defined:

// main.js, first file loaded
import {Iterable} from 'immutable';
Iterable.prototype[Symbol.for('get')] = function(value) {return this.get(value); };

and everything works (also nested destructuring, or destructuring with default values)

import {fromJS} from 'immutable';
const map = fromJS({author: {name: {first: "John", last: "Doe"}, birthdate: "10-10-2010"}});
const {author: {name: {first, last}, birthdate}} = map;

Disclaimer: I'm one of the authors of the plugin mentioned above.