Chumpocomon
Chumpocomon

Reputation: 733

Alternative to lodash omit

I would like to delete a property and return a new object without mutating the original object.

I know we can do this easily with Lodash like this:

const profile = { name: 'Maria', age: 30 }
_.omit(profile, name) // it returns a new object without the property name {age: 30}

However, I would like to know if it's possible to do it with vanilla JavaScript without assigning that value to undefined or using a filter?

Upvotes: 20

Views: 17068

Answers (6)

aremay
aremay

Reputation: 133

Slight variation of the accepted answer that just uses rest params:

const omit = (o, ...paths) => 
 Object.fromEntries(Object.entries(o).filter(([k]) => !paths.includes(k)))

Upvotes: 0

Dang Khoa
Dang Khoa

Reputation: 31

you can try this.

export const flattenKeys = (s) =>
  s
    .replace(/\[(\w+)\]/g, '.$1')
    .replace(/^\./, '')
    .split('.');

export const omit = (object, path) => {
  const obj = object;

  let keys = path;

  if (typeof keys === 'string') {
    keys = flattenKeys(keys);
  }

  if (keys.length === 1) {
    delete obj[keys];

    return undefined;
  }

  return omit(obj[keys[0]], keys.slice(1).join('.'));
};

Example:

const data = {
  user: {
    name: 'Khoa',
    age: 24
  },
  company: {
    name: 'Test',
  }
}

omit(data, 'company.name')

// output:
// { user: { name: 'Khoa', age: 24 }, company: {} }

Upvotes: 3

js_god_63552
js_god_63552

Reputation: 101

 const obj = { 
   prop0: 0, 
   prop1: 1, 
   prop2: 2, 
   prop3: 3, 
 };
   
 const prunedObj = (({ prop1, prop2, ...rest }) => rest)(obj);

 // prunedObj => { prop0: 0, prop3: 3}

Upvotes: 10

ahhmarr
ahhmarr

Reputation: 2320

wrote a package just to solve this issue

https://www.npmjs.com/package/fp-omit

it doesn't mutate or uses delete under the hood, but pure functional rambda function

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191986

For a single key you can destructure the object, and use computed property with rest to create an object without the property:

const omitSingle = (key, { [key]: _, ...obj }) => obj
const profile = { name: 'Maria', age: 30 }

const result = omitSingle('name', profile)

console.log(result)

To omit multiple properties, you can convert the object to [key, value] pairs, filter the pairs according to the listed keys array, and then convert back to an object via Object.fromEntries():

const omit = (keys, obj) => 
  Object.fromEntries(
    Object.entries(obj)
      .filter(([k]) => !keys.includes(k))
  )
  
const profile = { name: 'Maria', gender: 'Female', age: 30 }

const result = omit(['name', 'gender'], profile)

console.log(result)

Upvotes: 32

Ahed Kabalan
Ahed Kabalan

Reputation: 855

If you don't have a nested object, try to clone as follows:

const profile = { name: 'Maria', age: 30 }

function deleteProperty(object, property){
  var clonedObject = JSON.parse(JSON.stringify(object));
  delete clonedObject[property];
  return clonedObject;
}

var newProfile = deleteProperty(profile, "name");

console.log(profile);
console.log(newProfile);

Upvotes: 1

Related Questions