CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-immutability-helper

Mutate a copy of data without changing the original source

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

function-operations.mddocs/

Function Operations

Function-based operations for complex transformations and custom logic. These operations allow you to apply custom functions to transform data based on current values.

Capabilities

Apply Operation

Applies a function to the current value and replaces it with the function's return value.

/**
 * Apply a function to the current value
 * @param fn - Function that receives the current value and returns new value
 * @returns Result of applying the function to the current value
 */
{ $apply: (v: T) => T }

Usage Examples:

import update from "immutability-helper";

// Transform numeric value
const obj = { count: 5 };
const doubled = update(obj, { count: { $apply: x => x * 2 } });
// Result: { count: 10 }

// Transform string value
const user = { name: 'alice' };
const capitalized = update(user, { 
  name: { $apply: name => name.charAt(0).toUpperCase() + name.slice(1) } 
});
// Result: { name: 'Alice' }

// Transform array
const data = { numbers: [1, 2, 3, 4, 5] };
const evensOnly = update(data, { 
  numbers: { $apply: arr => arr.filter(n => n % 2 === 0) } 
});
// Result: { numbers: [2, 4] }

// Complex object transformation
const product = { 
  name: 'laptop', 
  price: 999, 
  specs: { ram: '8GB', storage: '256GB' }
};
const updated = update(product, { 
  specs: { 
    $apply: specs => ({
      ...specs,
      ram: '16GB',
      gpu: 'Integrated'
    })
  }
});
// Result: specs now has ram: '16GB' and new gpu property

Shorthand Function Syntax

Instead of using { $apply: function }, you can pass a function directly as the specification.

/**
 * Shorthand syntax for applying a function
 * @param fn - Function that receives the current value and returns new value
 * @returns Result of applying the function to the current value
 */
(v: T) => T

Usage Examples:

import update from "immutability-helper";

// Shorthand syntax (equivalent to $apply)
const obj = { value: 10 };

// These are equivalent:
const result1 = update(obj, { value: { $apply: x => x + 5 } });
const result2 = update(obj, { value: x => x + 5 });
// Both result in: { value: 15 }

// Multiple shorthand functions
const data = { a: 1, b: 2, c: 3 };
const transformed = update(data, {
  a: x => x * 2,
  b: x => x + 10,
  c: x => x.toString()
});
// Result: { a: 2, b: 12, c: '3' }

// Nested shorthand
const nested = { 
  user: { age: 25, scores: [80, 85, 90] },
  meta: { count: 3 }
};
const result = update(nested, {
  user: {
    age: age => age + 1,
    scores: scores => [...scores, 95]
  },
  meta: {
    count: count => count + 1
  }
});
// Result: user.age = 26, scores has 95 added, meta.count = 4

Advanced Function Operations

import update from "immutability-helper";

// Conditional updates
const user = { name: 'Alice', role: 'user', loginCount: 5 };
const conditionalUpdate = update(user, {
  role: currentRole => currentRole === 'user' && user.loginCount > 3 ? 'trusted' : currentRole,
  loginCount: count => count + 1
});

// Async function handling (Note: $apply itself is synchronous)
const processData = (data: string[]) => {
  return update(data, {
    $apply: items => items.map(item => item.toUpperCase()).sort()
  });
};

// Using external context
const multiplier = 3;
const numbers = { values: [1, 2, 3, 4] };
const scaled = update(numbers, {
  values: { $apply: arr => arr.map(n => n * multiplier) }
});

// Combining with other operations
const complex = { 
  items: [{ id: 1, active: false }, { id: 2, active: true }],
  count: 2
};
const processed = update(complex, {
  items: {
    $apply: items => items.map(item => ({ ...item, active: !item.active }))
  },
  count: count => count * 2
});

Error Handling

Function operations validate their inputs:

  • $apply requires the spec value to be a function
  • Functions should return a value (undefined results are allowed but may cause issues)
  • Functions are called synchronously and should not throw errors
// This will throw an error:
update({ value: 1 }, { value: { $apply: 'not a function' } });
// Error: update(): expected spec of $apply to be a function

// Functions should handle edge cases:
const safeUpdate = update(obj, {
  value: { 
    $apply: (current) => {
      if (typeof current !== 'number') return 0;
      return current * 2;
    }
  }
});

Performance Notes

  • Functions are called once per update operation
  • The function receives the current value as its argument
  • Return values replace the current value entirely
  • Reference equality is preserved if the function returns the same reference
  • Functions should be pure (no side effects) for predictable behavior
  • Avoid expensive computations in frequently called update functions

Best Practices

// Good: Pure function
const increment = (x: number) => x + 1;
update(obj, { count: { $apply: increment } });

// Good: Simple transformation
update(user, { name: name => name.trim().toLowerCase() });

// Avoid: Side effects
update(obj, { 
  value: { 
    $apply: x => {
      console.log(x); // Side effect - avoid this
      return x * 2;
    }
  }
});

// Good: Handle edge cases
update(data, {
  items: {
    $apply: items => Array.isArray(items) ? items.filter(Boolean) : []
  }
});

docs

array-operations.md

extension-system.md

function-operations.md

index.md

map-set-operations.md

object-operations.md

tile.json