Immutably Rename Object Keys in Javascript

Yazeed Bzadough
Jan 28, 2018 · 4 min read

Edit: See how to rename many object keys here.

If you’re okay with mutating data, renaming an object’s key is easy.

obj = { name: 'Bobo' }
obj.somethingElse =

If you don’t want to mutate your data, however, consider this function.

renameProp = (
{ [oldProp]: old, ...others }
) => ({
[newProp]: old,

What’s happening here:

Let’s add a debugger and inspect.

renameProp = (
{ [oldProp]: old, ...others }
) => {
return {
[newProp]: old,

Imagine we have an object, bobo.

bobo = {
name: 'Bobo',
job: 'Front-End Master',
age: 25

And we want to change bobo’s name to firstName, so we plug him into renameProp.

renameProp('name', 'firstName', bobo)

Our local variables are

  • oldProp: the first parameter, 'name'
  • newProp: the second parameter, 'firstName'
  • old: A computed property name based on oldProp. It’s
  • others: All of bobo's other properties

Let’s dive into line 4 of our code.

{ [oldProp]: old, ...others }

Dynamically find bobo’s name

Our function’s oldProp param is ‘name’, right? And the third parameter, the object, is bobo, so typing bobo[oldProp] would return

The first half of line 4 uses oldProp to find bobo's name and assigns it to a new variable, old.

Gather bobo’s other properties

Now let’s focus on line 4’s other half.

Our function must change one of bobo's property names without mutating him, so bobo's other properties must remain untouched. We use spread syntax to achieve this.

Spread syntax is a beautiful shorthand for gathering bobo’s other properties and assigning them a variable named others.

Let’s write a similar function to cement the concept into our heads.

getPropsWithout = (names, object) => Object.keys(object)
.filter((key) => !names.includes(key))
.reduce((newObject, currentKey) => ({
[currentKey]: object[currentKey]
}), {})

Don’t think about that function too much (unless you’re feeling adventurous! 😁). Just know that it takes an array of properties to exclude from a given object. We can use it like so:

boboNoName = getPropsWithout(['name'], bobo)

Since we’re only omitting name, boboNoName is identical to our others variable that used spread syntax.

See my article on spread if you’d like a deeper look!

Let’s recap!

Again, our local variables are

  • oldProp: ‘name’ because it’s the first parameter
  • newProp: ‘firstName’ because it’s the second parameter
  • old: ‘Bobo’ because we dynamically assigned it using computed property names.
  • others: { job: ‘Front-End Master’, age: 25 } because we used spread syntax to dynamically assign it. (Check out my spread article! 😁)

Now let’s focus on the return statement.

return {
[newProp]: old,

Computed property names are being leveraged once again. We dynamically create a new object and set its firstName to old. It’s like writing

// remember,
// old = 'Bobo'
// newProp = 'firstName'
newBobo = {}newBobo[newProp] = old
// OR
newBobo.firstName = old

Finally, we merge others with the new object. If you’re familiar with Object.assign, it’s just like writing

return Object.assign({}, newBobo, others)

Now bobo has a firstName!

And the original bobo is left unaffected.

Fun fun, until next time!

Take care,
Yazeed Bzadough

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade