or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

collections.mdfunctional-api.mdindex.mdsequences.mdutilities.md
tile.json

functional-api.mddocs/

Functional API

Overview

The functional API provides utility functions for working with immutable data structures in a functional programming style. These functions work with any Collection and provide an alternative to method chaining.

Core Imports

import { 
  fromJS, is, 
  get, has, set, remove, update,
  getIn, hasIn, setIn, removeIn, updateIn,
  merge, mergeWith, mergeDeep, mergeDeepWith
} from 'immutable';

Data Conversion

fromJS

Converts plain JavaScript objects and arrays to Immutable collections recursively.

function fromJS<T>(
  jsValue: T, 
  reviver?: (
    key: string | number, 
    sequence: Collection.Indexed<unknown> | Collection.Keyed<string, unknown>,
    path?: Array<string | number>
  ) => unknown
): T extends ReadonlyArray<infer U> 
  ? List<U> 
  : T extends object 
    ? Map<string, unknown> 
    : T;

Parameters

  • jsValue: JavaScript value to convert
  • reviver (optional): Function to transform values during conversion

Usage Examples

import { fromJS } from 'immutable';

// Basic conversion
const data = fromJS({
  users: [
    { id: 1, name: 'Alice', active: true },
    { id: 2, name: 'Bob', active: false }
  ],
  settings: {
    theme: 'dark',
    notifications: true
  }
});

// Results in:
// Map {
//   "users" => List [
//     Map { "id" => 1, "name" => "Alice", "active" => true },
//     Map { "id" => 2, "name" => "Bob", "active" => false }
//   ],
//   "settings" => Map {
//     "theme" => "dark",
//     "notifications" => true
//   }
// }

// With custom reviver
const withReviver = fromJS([1, 2, 3, 4], (key, value, path) => {
  return value.toOrderedSet();
});
// Results in OrderedSet { 1, 2, 3, 4 }

// Complex reviver example
const customData = fromJS({
  timestamp: '2023-01-01T00:00:00Z',
  tags: ['important', 'urgent'],
  metadata: { priority: 'high' }
}, (key, value) => {
  if (key === 'timestamp') {
    return new Date(value);
  }
  if (key === 'tags') {
    return value.toOrderedSet();
  }
  return value;
});

Value Equality

is

Performs deep value equality comparison using Immutable's equality semantics.

function is(valueA: unknown, valueB: unknown): boolean;

Usage Examples

import { is, List, Map } from 'immutable';

// Primitive values
console.log(is(1, 1)); // true
console.log(is(NaN, NaN)); // true (unlike ===)
console.log(is(0, -0)); // true (unlike Object.is)

// Collections
const list1 = List([1, 2, 3]);
const list2 = List([1, 2, 3]);
const list3 = List([1, 2, 4]);

console.log(is(list1, list2)); // true (value equality)
console.log(list1 === list2); // false (reference equality)
console.log(is(list1, list3)); // false (different values)

// Nested structures
const map1 = Map({ a: List([1, 2]), b: 3 });
const map2 = Map({ a: List([1, 2]), b: 3 });
console.log(is(map1, map2)); // true

// Custom value objects
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  
  valueOf() {
    return `${this.x},${this.y}`;
  }
}

const point1 = new Point(1, 2);
const point2 = new Point(1, 2);
console.log(is(point1, point2)); // true (uses valueOf)

Single-Level Operations

get

Gets a value from a collection.

function get<K, V>(collection: Collection<K, V>, key: K, notSetValue?: V): V | undefined;

has

Checks if a collection contains a key.

function has<K, V>(collection: Collection<K, V>, key: K): boolean;

set

Sets a value in a collection, returning a new collection.

function set<K, V>(collection: Collection<K, V>, key: K, value: V): Collection<K, V>;

remove

Removes a key from a collection, returning a new collection.

function remove<K, V>(collection: Collection<K, V>, key: K): Collection<K, V>;

update

Updates a value in a collection using an updater function.

function update<K, V>(collection: Collection<K, V>, key: K, updater: (value: V) => V): Collection<K, V>;
function update<K, V>(collection: Collection<K, V>, key: K, notSetValue: V, updater: (value: V) => V): Collection<K, V>;

Usage Examples

import { Map, List, get, has, set, remove, update } from 'immutable';

const map = Map({ a: 1, b: 2, c: 3 });
const list = List([10, 20, 30]);

// get
console.log(get(map, 'a')); // 1
console.log(get(list, 1)); // 20
console.log(get(map, 'x', 'default')); // 'default'

// has
console.log(has(map, 'b')); // true
console.log(has(list, 5)); // false

// set
const newMap = set(map, 'd', 4); // Map { a: 1, b: 2, c: 3, d: 4 }
const newList = set(list, 1, 25); // List [ 10, 25, 30 ]

// remove
const removedMap = remove(map, 'b'); // Map { a: 1, c: 3 }
const removedList = remove(list, 0); // List [ 20, 30 ]

// update
const updatedMap = update(map, 'a', val => val * 10); // Map { a: 10, b: 2, c: 3 }
const updatedList = update(list, 0, val => val + 5); // List [ 15, 20, 30 ]

// update with notSetValue
const updatedNew = update(map, 'x', 0, val => val + 1); // Map { a: 1, b: 2, c: 3, x: 1 }

Deep Operations

getIn

Gets a value from a nested collection structure.

function getIn<C>(collection: C, keyPath: Iterable<unknown>, notSetValue?: unknown): unknown;

hasIn

Checks if a nested collection structure contains a key path.

function hasIn<C>(collection: C, keyPath: Iterable<unknown>): boolean;

setIn

Sets a value in a nested collection structure.

function setIn<C>(collection: C, keyPath: Iterable<unknown>, value: unknown): C;

removeIn

Removes a value from a nested collection structure.

function removeIn<C>(collection: C, keyPath: Iterable<unknown>): C;

updateIn

Updates a value in a nested collection structure using an updater function.

function updateIn<C>(collection: C, keyPath: Iterable<unknown>, updater: (value: unknown) => unknown): C;
function updateIn<C>(collection: C, keyPath: Iterable<unknown>, notSetValue: unknown, updater: (value: unknown) => unknown): C;

Usage Examples

import { fromJS, getIn, hasIn, setIn, removeIn, updateIn } from 'immutable';

const nested = fromJS({
  users: [
    { 
      id: 1, 
      profile: { 
        name: 'Alice', 
        settings: { theme: 'dark', lang: 'en' } 
      } 
    },
    { 
      id: 2, 
      profile: { 
        name: 'Bob', 
        settings: { theme: 'light', lang: 'es' } 
      } 
    }
  ],
  config: {
    app: { version: '1.0.0', debug: true }
  }
});

// getIn
console.log(getIn(nested, ['users', 0, 'profile', 'name'])); // 'Alice'
console.log(getIn(nested, ['config', 'app', 'version'])); // '1.0.0'
console.log(getIn(nested, ['users', 0, 'missing'], 'default')); // 'default'

// hasIn
console.log(hasIn(nested, ['users', 1, 'profile', 'settings', 'theme'])); // true
console.log(hasIn(nested, ['users', 2])); // false

// setIn - creates intermediate structure if needed
const updated1 = setIn(nested, ['users', 0, 'profile', 'email'], 'alice@example.com');
const updated2 = setIn(nested, ['new', 'deep', 'path'], 'value');

// removeIn
const removed = removeIn(nested, ['users', 0, 'profile', 'settings', 'lang']);

// updateIn
const updated3 = updateIn(nested, ['config', 'app', 'version'], version => 
  version.split('.').map(n => parseInt(n)).join('.')
);

// updateIn with notSetValue
const updated4 = updateIn(nested, ['users', 0, 'profile', 'loginCount'], 0, count => count + 1);

// Complex path operations
const userPath = ['users', 1, 'profile', 'settings'];
const updatedSettings = updateIn(nested, userPath, settings => 
  settings.set('notifications', true).set('theme', 'auto')
);

Merge Operations

merge

Shallow merges collections or objects into a collection.

function merge<C>(collection: C, ...collections: Array<Partial<C> | Iterable<[unknown, unknown]> | {[key: string]: unknown}>): C;

mergeWith

Shallow merges with a custom merger function for conflicting keys.

function mergeWith<C>(
  merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
  collection: C, 
  ...collections: Array<Partial<C> | Iterable<[unknown, unknown]> | {[key: string]: unknown}>
): C;

mergeDeep

Deep merges collections or objects into a collection.

function mergeDeep<C>(collection: C, ...collections: Array<Partial<C> | Iterable<[unknown, unknown]> | {[key: string]: unknown}>): C;

mergeDeepWith

Deep merges with a custom merger function for conflicting values.

function mergeDeepWith<C>(
  merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
  collection: C, 
  ...collections: Array<Partial<C> | Iterable<[unknown, unknown]> | {[key: string]: unknown}>
): C;

Usage Examples

import { Map, fromJS, merge, mergeWith, mergeDeep, mergeDeepWith } from 'immutable';

const base = Map({ 
  a: 1, 
  b: 2, 
  nested: Map({ x: 10, y: 20 }) 
});

// merge - shallow
const merged1 = merge(base, { b: 3, c: 4 });
// Map { a: 1, b: 3, c: 4, nested: Map { x: 10, y: 20 } }

const merged2 = merge(base, { nested: Map({ z: 30 }) });
// Map { a: 1, b: 2, nested: Map { z: 30 } } - nested is replaced, not merged

// mergeWith - custom conflict resolution
const mergedWith = mergeWith(
  (oldVal, newVal, key) => {
    if (key === 'b') return oldVal + newVal; // Sum for key 'b'
    return newVal;
  },
  base,
  { b: 3, c: 4 }
);
// Map { a: 1, b: 5, c: 4, nested: Map { x: 10, y: 20 } }

// mergeDeep - recursive merging
const deepBase = fromJS({
  user: {
    profile: { name: 'Alice', age: 25 },
    settings: { theme: 'dark', lang: 'en' }
  },
  app: { version: '1.0' }
});

const deepMerged = mergeDeep(deepBase, {
  user: {
    profile: { age: 26, email: 'alice@example.com' },
    settings: { notifications: true }
  },
  app: { debug: true }
});
// Deeply merges all nested structures

// mergeDeepWith - custom deep conflict resolution
const deepMergedWith = mergeDeepWith(
  (oldVal, newVal, key) => {
    if (key === 'age' && typeof oldVal === 'number' && typeof newVal === 'number') {
      return Math.max(oldVal, newVal); // Keep higher age
    }
    return newVal;
  },
  deepBase,
  {
    user: {
      profile: { age: 20, status: 'active' }
    }
  }
);

// Multiple source merging
const multi = merge(
  Map({ a: 1 }),
  { b: 2 },
  Map([['c', 3]]),
  { d: 4 }
);
// Map { a: 1, b: 2, c: 3, d: 4 }

Functional Composition

The functional API enables clean composition and piping:

import { Map, get, set, update, updateIn, mergeDeep } from 'immutable';

const state = Map({
  user: Map({
    id: 1,
    profile: Map({ name: 'Alice', score: 100 })
  }),
  ui: Map({ theme: 'light' })
});

// Function composition
const incrementScore = (state) => 
  updateIn(state, ['user', 'profile', 'score'], score => score + 10);

const setTheme = (theme) => (state) => 
  set(state, 'ui', get(state, 'ui').set('theme', theme));

const addNotification = (message) => (state) =>
  update(state, 'notifications', List(), notifications => 
    notifications.push(Map({ message, timestamp: Date.now() }))
  );

// Compose operations
const newState = [
  incrementScore,
  setTheme('dark'),
  addNotification('Score updated!')
].reduce((state, fn) => fn(state), state);

// Utility function for deep updates
const deepUpdate = (keyPath, updater) => (collection) =>
  updateIn(collection, keyPath, updater);

// Pipeline of operations
const pipeline = [
  deepUpdate(['user', 'profile', 'name'], name => name.toUpperCase()),
  deepUpdate(['user', 'profile', 'score'], score => Math.min(score, 1000)),
  (state) => mergeDeep(state, { 
    user: { lastUpdate: new Date().toISOString() }
  })
];

const finalState = pipeline.reduce((state, fn) => fn(state), state);