How can I check if multiple properties exists on an object without being too verbose?
You can keep a reference to settings
, which improves things a fair bit:
const verifyJanrainAppSettings = (options) => {
const settings = options.JanrainAppSettings && options.JanrainAppSettings.settings;
return settings &&
settings.tokenUrl &&
settings.capture && // ** This was missing in the question, but I think you need it
settings.capture.clientId &&
settings.capture.appId &&
settings.capture.appDomain &&
settings.capture.captureServer &&
settings.httpLoadUrl &&
settings.httpsLoadUrl;
};
While you could put some of those names in an array and use a loop, I think I'd leave it at that.
With optional chaining (new in ES2020), that first line could be:
const settings = options.JanrainAppSettings?.settings;
The array version would look something like:
const settingsProps = "capture tokenUrl httpLoadUrl httpsLoadUrl".split(" ");
const captureProps = "clientId appId appDomain captureServer".split(" ");
const verifyJanrainAppSettings = (options) => {
const settings = options.JanrainAppSettings && options.JanrainAppSettings.settings;
return settings &&
settingsProps.every(prop => settings[prop]) &&
captureProps.every(prop => settings.capture[prop]);
};
adiga asks a good question. If you want existence rather than truthiness (you have truthiness in your question), you'll want in
(or for an own property check, hasOwnProperty
). For instance:
const settingsProps = "capture tokenUrl httpLoadUrl httpsLoadUrl".split(" ");
const captureProps = "clientId appId appDomain captureServer".split(" ");
const verifyJanrainAppSettings = (options) => {
const settings = options.JanrainAppSettings && options.JanrainAppSettings.settings;
return settings &&
settingsProps.every(prop => prop in settings) &&
captureProps.every(prop => prop in settings.capture);
};
I would opt for an utility function:
function contains(object, ...keys) {
return keys.every((key) => key in object)
}
const verifyJanrainAppSettings = (options) => {
return (
contains(options.JanrainAppSettings, 'settings') &&
contains(
options.JanrainAppSettings.settings,
'tokenUrl',
'httpLoadUrl',
'httpsLoadUrl',
'capture'
) &&
contains(
options.JanrainAppSettings.settings.capture,
'clientId',
'appId',
'appDomain',
'captureServer'
)
)
}
Perhaps something like if (['my', 'options'] in myObject) ...
This is the right idea. However, you need to loop over the array of strings and check if each of them is in myObject
. You can do this loop with Array.every()
. The only disadvantage is this only works at the deepest level. Since you have several levels of nesting here it will still get kind of ugly:
const verifyJanrainAppSettings = (options) => {
return options.JanrainAppSettings
&& options.JanrainAppSettings.settings // dont' forget this check
&& ['tokenUrl', 'httpLoadUrl', 'httpsLoadUrl', 'capture'].every(key => // added options.JanrainAppSettings.settings.capture check
key in options.JanrainAppSettings.settings
)
&& ['clientId', 'appId', 'appDomain', 'captureServer'].every(key =>
key in options.JanrainAppSettings.settings.capture
);
}