npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

immutable-setter

v1.1.2

Published

'Deep properties setter and getter for immutable objects'

Downloads

127

Readme

Motivation

There is a lot written about advantages of using immutable data structures in you code. The problem with JavaScrip that it is require en extra effort, "syntactical noise" and discipline because immutability is not "enforced" by the league. Especially if need to update deeply nested object structure.

To help with this problems library like Immutable.js can be used. Immutable.js uses special version containers like Set, Map etc. and special version of object class called Record to enforce immutability in your code.

A different approach is taken by popular application state management library Redux that treat application state as immutable object. Redux uses pure functions (called reducers). Reducer function accept original parts of the State object and modification parameters (actions) and return the new State Part with changes applied. Redux "updates" the application State by "cascading" calls to reducers with corresponding State Parts and "reassembling" the State in immutable fashion.

Idea of immutable-setter (This library) is to modify, retrieve and delete deeply nested parts of regular JavaScript object structure in immutable fusion. (Functions: setIn, getIn, deleteIn). Immutable-setter functions do not modify original object, but return new object that contains modification. Immutable-setter preserves Structural Sharing - only modified parts of the object structure are copied.

Immutable-setter uses concept of KeyPath to specify target parts of the object structure. KeyPath is an array of keys and indexes that describe the path to the target part of the object structure.

Immutable-setter gracefully handles situations when KeyPath points to the missing parts of the Object Structure:

  • setIn - missing parts will be generated. Immutable-setter infers type (Object vs. Array) to be generated based on KeyPath part pointing to the object's children. If key is a string then Object class instance is created, if key is and Integer or undefined - Array instance is created.
  • getIn - if any part of the object structure is missing it will return undefined
  • deleteIn - will do nothing

Please see Examples bellow and Unit tests for more details.

Examples


//update existing property deep in the object structure 'bar' -> 'baz'
constant original1 = {
    a: 'foo',
    b: [{
        c: 'bar'
    }]
}
constant result1 = setIn(original1, ['b', 0, 'c'], 'baz') 
> result1: {
    a: 'foo',
    b: [{
        c: 'baz'
    }]
}

//create sub object and set property
constant original2 = {
    a: 'foo'
}
constant result2 = setIn(original2, ['b', 'c'], 'bar') 
> result2: {
    a: 'foo', 
    b: {
        c: 'bar'
    }
}

//append object to the not existing yet array
constant original3 = {
    a: 'foo'
}
constant result3 = setIn(original3, ['b', undefined], {c: 'bar'}) 
> result3: {
    a: 'foo', 
    b: [{ 
        c: 'bar'
    }]
} 

//create new object with the value and append it to the array that not yet exists
constant original4 = {
    a: 'foo'
}
constant result4 = setIn(original4, ['b', undefined, 'c'], 'bar')
> result4: { 
    a:'foo', 
    b: [{
        c:'bar'
    }]
}

For more examples check the test file

API

setIn(object: Object, keyPath: Array<String|Number(Int)|undefined>, value: Any) => Object
  • object - plain javascript object. It will be treated as immutable.

  • keyPath - array of keys and indexes specifying path to the property to be set in the objects hierarchy. Can contain undefined keys indicating that value should be pushed to the end of the array.

  • value - new value to be set

  • return - new object with new objects created along the keyPath

deleteIn(object: Object, keyPath: Array<String|Number(Int)>) => Object
  • object - plain javascript object. It will be treated as immutable.

  • keyPath - array of keys and indexes specifying path to the property to be deleted in the objects hierarchy.

  • return - new object with new objects created along the keyPath if specified keyPath value was deleted. It returns original objects if value along keyPath was not found

getIn(object: Object, keyPath: Array<String|Number(Int)|undefined>) => Any|undefined
  • object - plain javascript object. It will be treated as immutable.
  • keyPath - array of keys and indexes specifying path of the property to read.

Alternatives

If Immutable.js is used - it provides a similar API for the Map object, except it requires all parts of the keyPath to be defined even if it is appending to the array (index of the new element).

The React Immutability Helpers library has more functionality for manipulating immutable values but I found the syntax a bit 'heavy' to read. Also, it does not support appending object to the non existing array. For example:

const newObj = update({}, {a: {b: {$push:[{c: 'foo'}]}}});
//This fails!
expect(newObj.a.b[0].c).to.be.equal("foo");

For non-immutable use cases deep-get-set can be used.

Installation and use

  • npm install immutable-setter
include { setIn, deleteIn, getIn } from 'immutable-setter'

To build and run tests

  • clone the repository
  • cd immutable-setter
  • npm test - this will build the library, generate the lib directory, and will run tests against the build.

License

MIT