CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-seamless-immutable

Immutable data structures for JavaScript which are backwards-compatible with normal JS Arrays and Objects.

Pending
Overview
Eval results
Files

array-operations.mddocs/

Array Operations

Methods for working with immutable arrays including functional operations, transformations, and element manipulation.

Capabilities

flatMap

Maps over array elements and flattens the results, similar to map followed by flatten.

/**
 * Maps and flattens array elements
 * @param {Array} array - Source array to process
 * @param {Function} iterator - Function that processes each element and returns a value or array
 * @returns {Array} New immutable array with mapped and flattened results
 */
function flatMap(array, iterator);

Usage Examples:

const Immutable = require("seamless-immutable");

const array = Immutable(["here", "we", "go"]);
const repeated = array.flatMap(function(str) {
  return [str, str, str];
});
// Result: ["here", "here", "here", "we", "we", "we", "go", "go", "go"]

// Filter out numbers by returning empty arrays
const mixed = Immutable(["drop the numbers!", 3, 2, 1, 0, null, undefined]);
const filtered = mixed.flatMap(function(value) {
  if (typeof value === "number") {
    return []; // Empty array removes the element
  } else {
    return value; // Non-arrays are treated as single elements
  }
});
// Result: ["drop the numbers!", null, undefined]

// Split strings into characters
const words = Immutable(["hello", "world"]);
const chars = words.flatMap(word => word.split(''));
// Result: ["h", "e", "l", "l", "o", "w", "o", "r", "l", "d"]

asObject

Converts an array to an object using key-value pairs, either from a provided iterator or assuming the array contains pairs.

/**
 * Convert array to object using key-value pairs
 * @param {Array} array - Source array to convert
 * @param {Function} [iterator] - Function that returns [key, value] pairs for each element
 * @returns {Object} New immutable object created from the array
 */
function asObject(array, iterator);

Usage Examples:

const Immutable = require("seamless-immutable");

// With iterator function
const array = Immutable(["hey", "you"]);
const obj = array.asObject(function(str) {
  return [str, str.toUpperCase()];
});
// Result: {hey: "HEY", you: "YOU"}

// Array already contains key-value pairs
const pairs = Immutable([["name", "Alice"], ["age", 30]]);
const person = pairs.asObject();
// Result: {name: "Alice", age: 30}

// Using with objects to extract keys
const users = Immutable([
  {id: 1, name: "Alice"},
  {id: 2, name: "Bob"}
]);
const usersById = users.asObject(user => [user.id, user]);
// Result: {1: {id: 1, name: "Alice"}, 2: {id: 2, name: "Bob"}}

// Iterator receives index as second parameter  
const indexed = Immutable(["a", "b", "c"]).asObject((value, index) => [index, value]);
// Result: {0: "a", 1: "b", 2: "c"}

set (Array-specific)

Sets an element at a specific index in an array.

/**
 * Set element at specific index in an array
 * @param {Array} array - Source array
 * @param {number} idx - Index to set (can be beyond current length)
 * @param {*} value - Value to set at the index
 * @param {Object} [config] - Configuration options
 * @param {boolean} [config.deep] - Deep merge if setting an object value
 * @returns {Array} New immutable array with element set
 */
function set(array, idx, value, config);

Usage Examples:

const Immutable = require("seamless-immutable");

const arr = Immutable([1, 2, 3]);

// Set existing index
const updated = arr.set(1, 99);
// Result: [1, 99, 3]

// Set beyond current length - fills with undefined
const extended = arr.set(5, "new");
// Result: [1, 2, 3, undefined, undefined, "new"]

// Deep merge when setting object values
const objArr = Immutable([{name: "Alice"}, {name: "Bob"}]);
const merged = objArr.set(0, {age: 30}, {deep: true});
// Result: [{name: "Alice", age: 30}, {name: "Bob"}]

// Using static method
const staticSet = Immutable.set(arr, 2, "replaced");
// Result: [1, 2, "replaced"]

asMutable (Array-specific)

Converts an immutable array to a mutable copy.

/**
 * Convert immutable array to mutable copy
 * @param {Array} array - Immutable array to convert
 * @param {Object} [options] - Conversion options  
 * @param {boolean} [options.deep] - Recursively convert nested immutable structures
 * @returns {Array} Mutable copy of the array
 */
function asMutable(array, options);

Usage Examples:

const Immutable = require("seamless-immutable");

const array = Immutable(["hello", "world"]);
const mutableArray = array.asMutable();

// Now can use mutating methods
mutableArray.push("!!!");
console.log(mutableArray); // ["hello", "world", "!!!"]

// Deep conversion for nested structures
const nested = Immutable([
  {name: "Alice", hobbies: ["reading"]},
  {name: "Bob", hobbies: ["coding"]}
]);

const shallowMutable = nested.asMutable();
// shallowMutable[0].name = "Charlie"; // Would still throw - nested objects still immutable

const deepMutable = nested.asMutable({deep: true});
deepMutable[0].name = "Charlie"; // Works - all nested structures are now mutable
deepMutable[0].hobbies.push("gaming"); // Also works

Enhanced Standard Array Methods

All standard non-mutating array methods are enhanced to return immutable arrays:

map, filter, slice, concat

/**
 * Enhanced array methods that return immutable results
 */
function map(callback, thisArg);
function filter(callback, thisArg);
function slice(start, end);  
function concat(...arrays);
function reduce(callback, initialValue);
function reduceRight(callback, initialValue);

Usage Examples:

const Immutable = require("seamless-immutable");

const numbers = Immutable([1, 2, 3, 4, 5]);

// All return immutable arrays
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const firstThree = numbers.slice(0, 3);
const extended = numbers.concat([6, 7, 8]);

console.log(Immutable.isImmutable(doubled)); // true
console.log(Immutable.isImmutable(evens)); // true
console.log(Immutable.isImmutable(firstThree)); // true
console.log(Immutable.isImmutable(extended)); // true

// Chaining works as expected
const result = numbers
  .map(n => n * 2)
  .filter(n => n > 4)
  .slice(0, 2);
// Result: [6, 8] (immutable)

keys

Returns an immutable result for object keys.

/**
 * Get array indices as an immutable array
 * @returns {Array} Immutable array of indices
 */
function keys();

Banned Mutating Methods

These methods throw ImmutableError when called on immutable arrays:

// These methods throw ImmutableError:
function push(...elements);    // Use concat() instead
function pop();               // Use slice(0, -1) instead  
function shift();             // Use slice(1) instead
function unshift(...elements); // Use concat(newElements, array) instead
function splice(start, deleteCount, ...items); // Use slice() and concat() instead
function sort(compareFn);     // Use slice().sort() on mutable copy instead
function reverse();           // Use slice().reverse() on mutable copy instead

Alternative Patterns:

const Immutable = require("seamless-immutable");
const arr = Immutable([1, 2, 3]);

// Instead of mutating methods, use immutable alternatives:

// Instead of push(4)
const withFour = arr.concat([4]);

// Instead of pop()
const withoutLast = arr.slice(0, -1);

// Instead of shift()  
const withoutFirst = arr.slice(1);

// Instead of unshift(0)
const withZero = [0].concat(arr);

// Instead of sort()
const sorted = arr.asMutable().sort(); // Convert to mutable first
// Or: const sorted = Immutable(arr.slice().sort());

// Instead of reverse()
const reversed = Immutable(arr.slice().reverse());

Instance vs Static Methods

All array methods are available in both instance and static forms:

const Immutable = require("seamless-immutable");
const arr = Immutable([1, 2, 3]);

// Instance methods (default API)
const mapped1 = arr.flatMap(x => [x, x]);
const obj1 = arr.asObject((val, idx) => [idx, val]);
const updated1 = arr.set(1, 99);

// Static methods (static API)
const ImmutableS = require("seamless-immutable").static;
const mapped2 = ImmutableS.flatMap(arr, x => [x, x]);
const obj2 = ImmutableS.asObject(arr, (val, idx) => [idx, val]);
const updated2 = ImmutableS.set(arr, 1, 99);

The static API is recommended when you want to avoid method name pollution or potential conflicts with existing array methods.

Install with Tessl CLI

npx tessl i tessl/npm-seamless-immutable

docs

array-operations.md

core.md

index.md

nested-operations.md

object-operations.md

tile.json