I want to know if an argument will throw if I use it in a key-value spread construction:
{ ...maybeIWillThrow }
I've got a bunch of functions that use spread to concisely implement "default options" behavior, like so:
const DEFAULTS = { bells: true, whistles: true }
function doThing( arg1, options ) {
let effectiveOptions = { ...DEFAULTS, ...options }
// do work...
}
Now I want to go back and add a few guard clauses to protect against calling with a non-hash options
argument. Using try/catch feels clunky because it requires two code blocks instead of one, and my preference would be a ternary or maybe a single-statement detour:
let effectiveOptions = spreadsLikeButter(options)
? { ...DEFAULTS, ...options }
: { ...DEFAULTS }
MDN suggests that testing for iterability is not right here (emphasis added):
Spread syntax (other than in the case of spread properties) can be applied only to iterable objects
I know I can protect against undefined
with default parameters, but that won't help if callers pass 5
or true
, and I assume typeof options === 'object'
will produce too many false positives (e.g. Date
, Promise
).
Is there a concise way to test a variable to see whether it will spread into an object without throwing?
Right now I'm wrapping try/catch in a willItBlend( value: any ): boolean
, but I'm hoping to replace that with something cleaner once I understand this better.
Also, I know I could move all the merge-with-defaults logic into a separate function that can hide the mess -- and maybe that's a good idea in my case -- but for academic purposes let's focus specifically on how to test a variable to determine wether it will spread.