Often I use objects to pass around a set of options.
In 99.9% of these cases I expect these objects to only contain a subset of the property I use. If an unexpected property is present, it means almost always that there's a typo or a logical error.
Is there a simple way to make sure that the option objects don't contain unexpected properties? I would only really need this during testing and debugging, so it doesn't have to be efficient.
Example:
function log( text, opts={} ) {
const {times=1, silent=false, logger=console} = opts
if (silent) return
for (let i=0; i<times; i++) {
logger.log( text )
}
}
// all good here
log( "Hello World!", {times:1} )
// "slient" is not a valid option. It's a typo.
// I want this call to throw an exception.
log( "Bye World!", {times:2, slient:true} )
I know that I can implement it through a function that receives the names of the expected properties:
function testOpts( opts={}, optNames=[] ) { /* ... */ }
testOpts( opts, ["times", "silent", "logger"] )
But maintaining this is boring and error prone: every time I change an option I need to update those parameters. I tried it and too often I forget to update it, so my function keeps accepting parameters that I removed, and this is something I want to avoid.
Is there a better solution that lets me write the property names only once?
If you only want to write them once, the only way to do that is in the log function where you are using them. There is indeed a way to do that: use rest syntax in the destructuring, and test that there are no other properties than the expected (destructured) ones:
function log( text, opts={} ) {
const {times=1, silent=false, logger=console, ...rest} = opts
// ^^^^^^^
assertEmpty(rest);
if (silent) return
for (let i=0; i<times; i++) {
logger.log( text )
}
}
function assertEmpty(val) {
const keys = Object.keys(val);
if (keys.length) {
throw new RangeError(`Unexpected properties ${keys.join(', ')} in object`);
}
}
Other than that, use a static analysis tool such as TypeScript or Flow, they will easily catch these mistakes.