How to Conditionally Insert Properties into a JavaScript Object Literal
This article explains how the spread operator combined with logical && can conditionally add properties to an object, detailing the underlying ECMAScript specification, the CopyDataProperties abstract operation, and edge cases with null, undefined, and primitive values.
In JavaScript you can conditionally add properties to an object literal using the spread syntax together with the logical && operator, e.g., const obj = { ...condition && { prop: value } };. This works because when condition is truthy, the expression evaluates to the object { prop: value }, which is then spread into obj. If condition is falsy, the spread receives a falsy value and nothing is added.
Example with form values
Suppose we have form values where state and priority may be optional:
const state = formValues['state'];
const priority = formValues['priority'];
const query = {
collection: 'Cats',
sort: 'asc',
...state && { state },
...priority && { priority },
};
await doQuery(query);The spread operator only inserts state or priority when the corresponding variable holds a truthy value.
Specification details
When the engine encounters ...condition && { prop: value }, the ECMAScript specification treats the spread operand as an AssignmentExpression . The result of the logical && is either the second operand (an object) or the first operand (a falsy value). The abstract operation CopyDataProperties then copies the enumerable own properties of the resulting object into the target object. CopyDataProperties performs the following steps (simplified):
Assert: Type(target) is Object.
Assert: excludedItems is a List of property keys.
If source is undefined or null, return target.
Let from be ! ToObject(source).
Let keys be ? from.[[OwnPropertyKeys]]().
For each nextKey of keys in List order, do
If nextKey is not in excludedItems, then
Let desc be ? from.[[GetOwnProperty]](nextKey).
If desc is not undefined and desc.[[Enumerable]] is true, then
Let propValue be ? Get(from, nextKey).
Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
Return target.If the spread operand is null or undefined, CopyDataProperties does nothing, effectively leaving the target unchanged.
Behavior with primitive values
When the operand evaluates to a primitive (boolean, string, number), the specification first boxes the primitive into its corresponding wrapper object. Since wrapper objects for booleans and numbers have no own enumerable properties, no properties are copied. For strings, the wrapper exposes the string characters as properties, but only a non‑empty string is truthy; an empty string is falsy and thus not spread.
Practical transformations
Truthy condition:
const obj = { ...condition && { prop: value } };
// becomes
const obj = { ...{ prop: value } };Falsy condition (e.g., null or undefined):
const obj = { ...null };
// results in an empty object
const obj = {};Overall, using ...condition && { key: value } provides a concise, side‑effect‑free way to conditionally merge properties without additional if‑else statements.
Conclusion
The spread‑and‑logical‑AND pattern leverages the ECMAScript abstract operation CopyDataProperties to safely and efficiently insert properties only when desired, handling edge cases like null, undefined, and primitive values gracefully.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
