Mutate a copy of data without changing the original source
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Function-based operations for complex transformations and custom logic. These operations allow you to apply custom functions to transform data based on current values.
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 propertyInstead 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) => TUsage 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 = 4import 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
});Function operations validate their inputs:
$apply requires the spec value to be a function// 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;
}
}
});// 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) : []
}
});