Immutable data structures for JavaScript which are backwards-compatible with normal JS Arrays and Objects.
—
Methods for working with immutable objects including merging, property manipulation, and transformations.
Merges objects immutably, with priority given to the provided object's values.
/**
* Merge objects immutably with configurable behavior
* @param {Object} obj - Target object to merge into
* @param {Object|Array} other - Object or array of objects to merge
* @param {Object} [config] - Merge configuration options
* @param {boolean} [config.deep] - Perform deep merge of nested objects
* @param {string} [config.mode] - Merge mode: 'merge' (default) or 'replace'
* @param {Function} [config.merger] - Custom merger function for property conflicts
* @returns {Object} New immutable object with merged properties
*/
function merge(obj, other, config);Usage Examples:
const Immutable = require("seamless-immutable");
const obj = Immutable({status: "good", hypothesis: "plausible", errors: 0});
// Basic merge
const merged = obj.merge({status: "funky", hypothesis: "confirmed"});
// Result: {status: "funky", hypothesis: "confirmed", errors: 0}
// Merge multiple objects using array
const multiMerged = obj.merge([
{status: "funky", errors: 1},
{status: "groovy", errors: 2},
{status: "sweet"}
]);
// Result: {status: "sweet", errors: 2, hypothesis: "plausible"}
// Deep merge nested objects
const nested = Immutable({
user: {name: "Alice", age: 30},
settings: {theme: "dark", lang: "en"}
});
const deepMerged = nested.merge({
user: {age: 31, city: "NYC"}
}, {deep: true});
// Result: {user: {name: "Alice", age: 31, city: "NYC"}, settings: {theme: "dark", lang: "en"}}
// Replace mode - removes properties not in the new object
const replaced = obj.merge({status: "new"}, {mode: 'replace'});
// Result: {status: "new"} - other properties removed
// Custom merger function
const customMerged = obj.merge({errors: 5}, {
merger: (oldVal, newVal) => {
if (typeof oldVal === 'number' && typeof newVal === 'number') {
return oldVal + newVal; // Add numbers instead of replacing
}
return newVal;
}
});
// Result: {status: "good", hypothesis: "plausible", errors: 5} (0 + 5)Replaces object properties entirely, equivalent to merge with {mode: 'replace'}.
/**
* Replace object properties entirely
* @param {Object} obj - Target object
* @param {Object} value - New properties to replace with
* @param {Object} [config] - Configuration options
* @param {boolean} [config.deep] - Perform deep comparison and preserve identical nested objects
* @returns {Object} New immutable object containing only the replacement properties
*/
function replace(obj, value, config);Usage Examples:
const Immutable = require("seamless-immutable");
const obj1 = Immutable({a: {b: 'test'}, c: 'test'});
const obj2 = obj1.replace({a: {b: 'test'}});
// Result: {a: {b: 'test'}} - property 'c' removed
// With deep option - preserves identical nested objects for performance
const obj3 = obj1.replace({a: {b: 'test'}}, {deep: true});
console.log(obj1.a === obj3.a); // true - same nested object reference preservedSets a single property on an object immutably.
/**
* Set a property on an object immutably
* @param {Object} obj - Target object
* @param {string} property - Property key to set
* @param {*} value - Value to set
* @param {Object} [config] - Configuration options
* @param {boolean} [config.deep] - Deep merge if setting an object value
* @returns {Object} New immutable object with property set
*/
function set(obj, property, value, config);Usage Examples:
const Immutable = require("seamless-immutable");
const obj = Immutable({type: "parrot", subtype: "Norwegian Blue", status: "alive"});
// Basic property setting
const updated = obj.set("status", "dead");
// Result: {type: "parrot", subtype: "Norwegian Blue", status: "dead"}
// Deep merge when setting object values
const withAddress = obj.set("address", {city: "London", country: "UK"}, {deep: true});
// Static method usage
const staticUpdate = Immutable.set(obj, "status", "sleeping");Removes properties from an object immutably.
/**
* Remove properties from an object immutably
* @param {Object} obj - Target object
* @param {...string|Array|Function} keys - Property keys to remove, array of keys, or predicate function
* @returns {Object} New immutable object without specified properties
*/
function without(obj, ...keys);Usage Examples:
const Immutable = require("seamless-immutable");
const obj = Immutable({the: "forests", will: "echo", with: "laughter"});
// Remove single property
const without1 = obj.without("with");
// Result: {the: "forests", will: "echo"}
// Remove multiple properties as separate arguments
const without2 = obj.without("will", "with");
// Result: {the: "forests"}
// Remove multiple properties as array
const without3 = obj.without(["will", "with"]);
// Result: {the: "forests"}
// Remove using predicate function
const without4 = obj.without((value, key) => key === "the" || value === "echo");
// Result: {with: "laughter"}
// Numeric keys are handled correctly
const objWithNumbers = Immutable({0: "zero", 1: "one", name: "test"});
const withoutNumbers = objWithNumbers.without(0, 1);
// Result: {name: "test"}Updates a property using an updater function.
/**
* Update a property using an updater function
* @param {Object} obj - Target object
* @param {string} property - Property key to update
* @param {Function} updater - Function that receives current value and returns new value
* @param {...*} [args] - Additional arguments passed to updater function
* @returns {Object} New immutable object with updated property
*/
function update(obj, property, updater, ...args);Usage Examples:
const Immutable = require("seamless-immutable");
// Simple increment
function inc(x) { return x + 1; }
const obj = Immutable({foo: 1});
const incremented = obj.update("foo", inc);
// Result: {foo: 2}
// Updater with additional arguments
function add(x, y) { return x + y; }
const added = obj.update("foo", add, 10);
// Result: {foo: 11}
// String manipulation
const user = Immutable({name: "alice"});
const capitalized = user.update("name", name => name.toUpperCase());
// Result: {name: "ALICE"}
// Working with arrays
const data = Immutable({items: [1, 2, 3]});
const withNewItem = data.update("items", items => items.concat(4));
// Result: {items: [1, 2, 3, 4]}Converts an immutable object to a mutable copy.
/**
* Convert immutable object to mutable copy
* @param {Object} obj - Immutable object to convert
* @param {Object} [options] - Conversion options
* @param {boolean} [options.deep] - Recursively convert nested immutable structures
* @returns {Object} Mutable copy of the object
*/
function asMutable(obj, options);Usage Examples:
const Immutable = require("seamless-immutable");
const obj = Immutable({when: "the", levee: "breaks"});
const mutableObject = obj.asMutable();
// Now can mutate directly
mutableObject.have = "no place to go";
console.log(mutableObject); // {when: "the", levee: "breaks", have: "no place to go"}
// Deep conversion for nested structures
const nested = Immutable({
user: {name: "Alice"},
hobbies: ["reading", "coding"]
});
const shallowMutable = nested.asMutable();
// shallowMutable.user.name = "Bob"; // Would still throw - nested objects still immutable
const deepMutable = nested.asMutable({deep: true});
deepMutable.user.name = "Bob"; // Works - all nested structures are now mutable
deepMutable.hobbies.push("gaming"); // Also worksAll object methods are available in both instance and static forms:
const Immutable = require("seamless-immutable");
const obj = Immutable({name: "Alice", age: 30});
// Instance methods (default API)
const merged1 = obj.merge({age: 31});
const updated1 = obj.set("status", "active");
const filtered1 = obj.without("age");
// Static methods (static API - avoids method pollution)
const Immutable = require("seamless-immutable").static;
const merged2 = Immutable.merge(obj, {age: 31});
const updated2 = Immutable.set(obj, "status", "active");
const filtered2 = Immutable.without(obj, "age");Both approaches are functionally identical - choose based on your preference for avoiding method name collisions or preferring shorter syntax.
Install with Tessl CLI
npx tessl i tessl/npm-seamless-immutable