Is there a clean way to return a new object that omits certain properties that the original object contains without having to use something like lodash?
const { bar, baz, ...qux } = foo
Now your object qux
has all of the properties of foo
except for bar
and baz
.
qux
will update the values in foo
. Javascript objects are passed by reference. –
Norvell qux
then foo
's value will not be updated. However, if the value of a property of qux
is an object and you change something in that object, then the object referenced by the corresponding property of foo
would also be changed. –
Butylene const { "bar", 'baz', ...qux } = foo
–
Tunic const x = "Anything"; const obj = { x: "Foo", y:"Bar"}; const {x, ...no_x} = obj;
–
Chokebore const { ["bar"]:bar, ["baz"]:bas, ...qux } = foo
If you have const objKey = "bar";
you can usr such syntax: const { [
${objKey}]:bar, ["baz"]:bas, ...qux } = foo
–
Ritenuto const { x: _x, ...no_x } = obj;
–
Befriend const _x = "Something"
was declared earlier this will fail, as _x
is being reassigned. Just feels odd there's not a good shorthand that doesn't force you to create new variables. –
Chokebore In modern environments you can use this code snippet:
function omit(key, obj) {
const { [key]: omitted, ...rest } = obj;
return rest;
}
If you know the list of the properties that you want preserved as well as omitted, the following "whitelisting" approach should work:
const exampleFilter = ({ keepMe, keepMeToo }) => ({ keepMe, keepMeToo })
console.log(
exampleFilter({
keepMe: 'keepMe',
keepMeToo: 'keepMeToo',
omitMe: 'omitMe',
omitMeToo: 'omitMeToo'
})
)
{ keepMe, keepMeToo }
is like { keepMe: keepMe, keepMeToo: keepMeToo }
. –
Calefaction There's the blacklist package on npm which has a very flexible api.
Also a situational trick using the object rest-spread proposal (stage-3).
const {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4};
a // 1
b // 2
rest // {c: 3, d: 4}
This is often used in react components where you want to use a few properties and pass the rest as props to a <div {...props} />
or similar.
A solution that hasn't been mentioned yet:
Omit single
o = {a: 5, b: 6, c: 7}
Object.fromEntries(Object.entries(o).filter(e => e[0] != 'b'))
// Object { a: 5, c: 7 }
Omit multiple
o = {a: 1, b: 2, c: 3, d: 4}
exclude = new Set(['a', 'b'])
Object.fromEntries(Object.entries(o).filter(e => !exclude.has(e[0])))
// Object { c: 3, d: 4 }
The Set
above is used because it leads to linearithmic complexity even if the number of elements in exclude
is in the same asymptotic equivalence class as the number of elements in o
.
Omit and array of keys, using ES7 w/ recursion.
function omit(keys, obj) {
if (!keys.length) return obj
const { [keys.pop()]: omitted, ...rest } = obj;
return omit(keys, rest);
}
This builds on top of @Eddie Cooro answer.
export function omitObjectKeys<T extends object = {}>( keys: string[], obj: T, ): Partial<T> { return (keys as any).reduce((a: Partial<T>, e: keyof T) => { const { [e]: omitted, ...rest } = a; return rest; }, obj); }
–
Modernistic You can use Object.assign(), delete
var not = ["a", "b"]; // properties to delete from obj object
var o = Object.assign({}, obj);
for (let n of not) delete o[n];
Alternatively
var props = ["c", "d"];
let o = Object.assign({}, ...props.map(prop => ({[prop]:obj[prop]})));
Sure, why not something like:
var original = {
name: 'Rory',
state: 'Bored',
age: '27'
};
var copied = Object.assign({}, original);
delete copied.age;
console.log(copied);
If you already use lodash, you may also do omit(obj, ["properties", "to", "omit"])
to get a new Object without the properties provided in the array.
Building on other answers: if there's not a need for reusability or abstraction this will remove blacklisted properties inline with an IIFE.
(
({
// Properties to remove from `someObject`.
omitMe,
omitMeToo,
// The rest of `someObject`, to keep.
...keep
}) => keep
)(someObject)
Example
const someObject = {
keepMe: 'keepMe',
keepMeToo: 'keepMeToo',
omitMe: 'omitMe',
omitMeToo: 'omitMeToo',
};
console.log(
(
({
omitMe,
omitMeToo,
...keep
}) => keep
)(someObject)
);
No answer seemed to allow nested path specifications using dot notation. Here's a solution for that:
const omit = (obj, keys) => {
if (!keys.length) return obj;
const key = keys.pop();
const parts = key.split(".");
if (parts.length > 1) {
const { [parts[0]]: todo, ...rest } = obj;
return {
...omit(rest, keys),
[parts[0]]: omit(todo, [parts[1]]),
};
}
const { [key]: omitted, ...rest } = obj;
return omit(rest, keys);
};
var obj = {
a: 1,
b: 2,
c: 3,
d: {
c: 3,
e: 5
}
};
console.log(omit(obj, ['b', 'd.c']));
We want to exclude specific property of an javascript object.
Sample Input:
const foo={ "bar":"sangram", "baz":"sagar", "mux":"sachin", "fch":"swapnil" }
we want to omit a 'bar' property of this object foo.
Sample Output:
const foo={ "baz":"sagar", "mux":"sachin", "fch":"swapnil" }
Solution:
const foo={ "bar":"sangram", "baz":"sagar", "mux":"sachin", "fch":"swapnil" } const { bar, ...qux } = foo console.log(qux)
Output:
{ baz: 'sagar', mux: 'sachin', fch: 'swapnil' }
function omitKeys(obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}
var obj = {
a: 1,
b: 2,
c: 3,
d: {
c: 3,
e: 5
}
};
Object.extract = function(obj, keys, exclude) {
var clone = Object.assign({}, obj);
if (keys && (keys instanceof Array)) {
for (var k in clone) {
var hasKey = keys.indexOf(k) >= 0;
if ((!hasKey && !exclude) || (hasKey && exclude)) {
delete clone[k];
}
}
}
return clone;
};
console.log('Extract specified keys: \n-----------------------');
var clone1 = Object.extract(obj, ['a', 'd']);
console.log(clone1);
console.log('Exclude specified keys: \n-----------------------');
var clone2 = Object.extract(obj, ['a', 'd'], true);
console.log(clone2);
const data = { name : 'Micheal', passowrd : 'password', age: '44'}
const dataClean = data.toObject();
delete dataClean.password;
console.log(dataClean);
Taking Grant Zvolsky's answer and turning it into functions
function omit(obj, key) {
return Object.fromEntries(Object.entries(obj).filter(e => e[0] != key))
}
/** Omits multiple keys. The exclude parameter is a Set of keys to exclude **/
function omitSet(obj, exclude) {
return Object.fromEntries(
Object.entries(obj).filter((e) => !exclude.has(e[0]))
);
}
o = {a: 1, b: 2, c: 3, d: 4}
exclude = new Set(['a', 'b'])
console.log(omitSet(o, exclude));
// Object { c: 3, d: 4 }
Or in Typescript:
function omitSet(obj: object, exclude: Set<string>) {
return Object.fromEntries(
Object.entries(obj).filter((e) => !exclude.has(e[0]))
);
}
Method for overwriting the value:
const props = { primary: true, anotherProp: "hello" };
const newProps = { ...props, primary: undefined }; // Overwrite primary property
result:
{ primary: undefined, anotherProp: "hello" }
Which is a useful case for React native elements:
<button
{...{ ...props, primary: undefined }}
type="button"
className="my-button"
/>
React should not pass the undefined value as an argument and this should also work with TypeScript.
Taking Jeremy's answer but with the following modifications:
- Adding type annotations (TypeScript)
- Handling of
Set
internally so that you can pass an arbitrary amount of strings to the resulting variadic function - Key arguments will only be allowed that are actual keys inside the object
The following is TypeScript, for anyone finding that useful. You can also just remove the type annotations and get JS if that's what you need.
function omit<T extends Record<string, any>, K extends keyof T>(
obj: T,
...keys: K[]
): Omit<T, K> {
// I'm sure this could be done in a better way,
// but if we don't do this we run into issues with
// the interaction between Object.entries() and
// Set<string | number | symbol>.
const omitKeys = new Set(keys as string[]);
return Object.fromEntries(
Object.entries(obj).filter(([k]) => !omitKeys.has(k)),
) as Omit<T, K>;
}
const obj = {
a: 1,
b: 2,
c: 4,
x: "hello",
y: "world",
};
console.log(omit(obj)); // { a: 1, b: 2, c: 4, x: "hello", y: "world" }
console.log(omit(obj, "x")); // { a: 1, b: 2, c: 4, y: "world" }
console.log(omit(obj, "x", "y")); // { a: 1, b: 2, c: 4 }
console.log(omit(obj, "d")); // Error! No property "d" in obj.
One solution, I'm sure many others exist.
const testObj = {
prop1: 'value1',
prop2: 'value2',
prop3: 'value3'
};
const removeProps = (...propsToFilter) => obj => {
return Object.keys(obj)
.filter(key => !propsToFilter.includes(key))
.reduce((newObj, key) => {
newObj[key] = obj[key];
return newObj;
}, {});
};
console.log(removeProps('prop3')(testObj));
console.log(removeProps('prop1', 'prop2')(testObj));
Edit: I always forget about delete
...
const testObj = {
prop1: 'value1',
prop2: 'value2',
prop3: 'value3'
};
const removeProps = (...propsToFilter) => obj => {
const newObj = Object.assign({}, obj);
propsToFilter.forEach(key => delete newObj[key]);
return newObj;
};
console.log(removeProps('prop3')(testObj));
console.log(removeProps('prop1', 'prop2')(testObj));
I saw this question and I wanted to remove 1 specific key, not a full method, so here's my suggestion:
const originalObj = {wantedKey: 111, anotherWantedKey: 222, unwantedKey: 1010};
const cleanedObj = Object.assign(originalObj, {unwantedKey: undefined});
unwantedKey
will be copied from the source to the target, yes, but it will be undefined
in the target. Do note however that Object.hasOwn(cleanedObj, "unwantedKey")
will be true
. Another point to note here is that originalObj
will also be modified, which may or may not be desirable. –
Befriend © 2022 - 2024 — McMap. All rights reserved.