A function that mutates one of its parameters in place and returns nothing — `addTax(order)` modifies `order.total` directly.
Instead of mutating a parameter in place, the function returns the modified value so the caller reassigns.
Before the refactoring
function addTax(order) {order.total *= 1.1;}addTax(order);
After the refactoring
function withTax(order) {return { ...order, total: order.total * 1.1 };}order = withTax(order);
Callers can't tell from the signature that a parameter is being mutated; snapshotting and equality become unreliable; functional composition is blocked.
Callers must remember to capture the returned value; if any forget, they keep the unmodified original. Mark the parameter readonly so the type system helps.
Side effects on inputs disappear; the function reads as a transformation; equality and snapshotting become possible.
Refactoring every parameter-mutator to return-modified-value, including ones where the in-place mutation is genuinely the contract callers want — a performance-sensitive batch operation, for example.