How to Resolve ESLint Error "Assignment to property of function parameter" (no-param-reassign) in JavaScript
The ESLint error Assignment to property of function parameter (rule: no-param-reassign) is designed to prevent a common practice that can lead to unexpected side effects: mutating a function's parameters. When you modify an object or array that was passed into a function, you are changing that object for all other parts of your application that reference it, which can make your code harder to debug and understand.
This guide will explain the root cause of this error—the concept of mutation—and provide the clean, modern solutions for fixing it. You will learn the best practice of creating a local copy before making changes, and how to configure or disable the rule when necessary.
Understanding the Root Cause: Mutation and Side Effects
This ESLint rule exists to encourage an immutable programming style. When you pass an object or array to a function, you are passing a reference to it, not a copy. Modifying a property on that parameter directly mutates the original object. This is known as a side effect.
Example of error:
const user = { id: 1, name: 'John' };
function addStatus(userObject) {
// ⛔️ Assignment to property of function parameter 'userObject'. (eslint no-param-reassign)
userObject.status = 'active'; // This MUTATES the original `user` object
return userObject;
}
const updatedUser = addStatus(user);
// The original `user` object has been changed, which might be unexpected.
console.log(user); // Output: { id: 1, name: 'John', status: 'active' }
The no-param-reassign rule flags this to prevent such unintended side effects.
Solution 1 (Best Practice): Create a Local Copy (Immutability)
The best way to fix this error is to follow the rule's advice and avoid mutating the parameter. You can do this by creating a local copy of the object inside your function.
The logic:
- Inside the function, create a new variable.
- Use the spread syntax (
...) orObject.assign()to create a shallow copy of the parameter object. - Modify the copy, leaving the original parameter untouched.
- Return the modified copy.
Solution:
const user = { id: 1, name: 'John' };
function addStatus(userObject) {
// Create a shallow copy of the parameter object
const newObject = { ...userObject };
// Modify the copy, not the original parameter
newObject.status = 'active';
return newObject;
}
const updatedUser = addStatus(user);
// The new object has the change
console.log(updatedUser); // Output: { id: 1, name: 'John', status: 'active' }
// The original `user` object is safely unchanged
console.log(user); // Output: { id: 1, name: 'John' }
This is the safest and most professional way to handle the issue.
Solution 2 (Pragmatic): Configure the Rule to Allow Property Modification
Sometimes, especially in codebases that use libraries like Redux Toolkit's Immer, mutating properties is a common and accepted pattern. In these cases, you can configure the no-param-reassign rule to be less strict.
The rule can be configured to allow modifying the properties of a parameter, while still forbidding the reassignment of the parameter itself (e.g., param = null).
The solution consists to set the props option for the rule to false in your .eslintrc.js or .eslintrc.json file
module.exports = {
// ...
rules: {
'no-param-reassign': ['error', { props: false }],
// ...
},
};
With this configuration, the original code from the "Error in Action" section will no longer produce an ESLint error.
Solution 3 (Last Resort): Disabling the Rule
While not recommended, you can disable the rule entirely if you are confident that the mutation is intended and safe.
Solution for a Single Line
function addStatus(userObject) {
// eslint-disable-next-line no-param-reassign
userObject.status = 'active';
return userObject;
}
Solution for an Entire File
Place this comment at the top of your file.
/* eslint-disable no-param-reassign */
Global Solution In Your .eslintrc.js File
module.exports = {
rules: {
'no-param-reassign': 'off',
},
};
Practical Example: Fixing the Error in Array.prototype.reduce
This error often appears when using reduce, as the accumulator is a function parameter that is intended to be modified.
The Problematic Code:
const arr = [{ id: 1 }, { id: 2 }];
// ⛔️ Assignment to property of function parameter 'acc'.
const result = arr.reduce((acc, obj) => {
acc[obj.id] = obj;
return acc;
}, {});
Solution with props: false
If you have configured the rule with { "props": false } as shown in Solution 2, this code will pass without errors. This is a common and practical configuration for projects that use reduce this way.
Solution (Strictly Immutable)
To satisfy the strict default rule, you must return a new object in each iteration.
const arr = [{ id: 1 }, { id: 2 }];
const result = arr.reduce((acc, obj) => {
// Return a new object that merges the accumulator and the new property
return {
...acc,
[obj.id]: obj
};
}, {});
Conclusion
The no-param-reassign ESLint rule is a valuable tool for promoting an immutable coding style and preventing unexpected side effects.
To fix it:
- The best practice is to create a local copy of the parameter object (using
{...obj}) and modify the copy instead of the original. - A good pragmatic compromise is to configure the rule in your
.eslintrc.jsfile to allow property modification:'no-param-reassign': ['error', { props: false }]. - Disabling the rule should be a last resort, used only when you are certain that mutating the parameter is safe and intended.