Reputation: 5666
I'm trying to find a way of creating an object where upon creation it ignores the values that are undefined.
In the example below, the variable someNames has unknown content when creating the object.
const someNames = {
catName: 'purry',
rabbitName: 'floppy',
turtleName: 'shelly'
};
const { catName, dogName, hamsterName, rabbitName } = someNames;
const animalNames = Object.assign({}, {
catName,
dogName,
hamsterName,
rabbitName
});
console.log(animalNames);// {catName: 'purry', rabbitName: 'floppy'}
What actually gets logged is this:
{
catName: 'purry',
dogName: undefined,
hamsterName: undefined,
rabbitName: 'floppy'
}
Upvotes: 14
Views: 14893
Reputation: 393
I think you can do that:
const someNames = {
catName: 'purry',
rabbitName: 'floppy',
turtleName: 'shelly'
};
const { catName, dogName, hamsterName, rabbitName } = someNames;
const animalNames = Object.assign({}, Object.fromEntries(Object.entries({
catName,
dogName,
hamsterName,
rabbitName
}).filter(([key,value])=>value!==undefined)));
console.log(animalNames);// {catName: 'purry', rabbitName: 'floppy'}
Upvotes: 0
Reputation: 4942
Old thread, however not quite pleased with previous answers. Thought I'd chip in on a cleaner solution:
const someNames = {
catName: 'purry',
rabbitName: 'floppy',
notAnAnimal: 'car',
};
const allowedKeys = ['catName', 'rabbitName'];
const animalNames = Object.keys(someNames).reduce((animals, key) => {
if (allowedKeys.includes(key)) animals[key] = someNames[key];
return animals;
}, {});
Upvotes: 3
Reputation: 5666
This is what I went for afterwards. It's just a refactor of @Bergi's code. I've done it this way because it has a reduced number of loops. @Bergi's answer allows for as many object parameters as possible. In this solution, you can just use spreads to create the second object if you have object spreads enabled in babel (https://babeljs.io/docs/plugins/transform-object-rest-spread/).
const someNames = {
catName: 'purry',
rabbitName: 'floppy',
turtleName: 'shelly'
};
function assignDefined(target, source) {
Object.keys(source).map((key, index) => {
if(source[key] !== undefined) {
target[key] = source[key];
}
});
return target;
}
const { catName, dogName, hamsterName, rabbitName } = someNames;
const animalNames = assignDefined({}, {
catName,
dogName,
hamsterName,
rabbitName
});
console.log(animalNames);
Thanks @Bergi!
Upvotes: 2
Reputation: 665090
Don't use Object.assign
which copies all own enumerable properties regardless of their value but your own custom function that can filter out undefined
properties:
function assignDefined(target, ...sources) {
for (const source of sources) {
for (const key of Object.keys(source)) {
const val = source[key];
if (val !== undefined) {
target[key] = val;
}
}
}
return target;
}
…
const animalNames = assignDefined({}, {
catName,
dogName,
hamsterName,
rabbitName
});
Upvotes: 10
Reputation: 2285
'use strict';
const someNames = {
catName: 'purry',
rabbitName: 'floppy'
};
const expectedProperties = ['catName', 'dogName', 'hamsterName', 'rabbitName'];
const animalNames = Object.assign({}, expectedProperties.reduce((o, prop) => (someNames[prop]) ? (o[prop] = someNames[prop]) && o : o, {}));
console.log(animalNames);
Upvotes: 1
Reputation: 2265
You could do something like this just to clean those properties
Object.keys(animalNames).forEach(function (key) {
if(animalNames[key] === undefined) delete animalNames[key];
});
Upvotes: 5