Using Guard Conditions To Short-Circuit Object-Spread Operations In TypeScript 3.2.4
After my post yesterday on applying the Object-Spread operator to Null and Undefined values in TypeScript, Duncan Bay showed me another cool feature of the Object-Spread operator: you can use guard conditions to short-circuit spread operations. Off the top of my head, I don't have a great use-case for this; but, I thought it was an idea worth sharing.
To see this in action, I'm going to create a new object into which I randomly spread two other objects:
interface StringMap {
[ key: string ]: string;
}
var target: StringMap = { a: "1" };
var value1: StringMap = { b: "2" };
var value2: StringMap = { c: "3" };
var clone: StringMap = {
...target,
// This is a silly example; but, it's demonstrating that the Object-Spread operator
// can use Boolean guard-conditions in order to short-circuit the individual spread
// actions: we are randomly executing the spread of the two other values.
...( ( Math.random() < .5 ) && value1 ),
...( ( Math.random() < .5 ) && value2 )
};
console.log( "Clone:", clone );
As you can see, I'm using the following generalized concept:
...( truthy && spreadable )
When the "truthy" value is True, the expression returns "spreadable", which is then spread into the new structure. However, when the "truthy" is False, the expression returns the "falsey" value, which TypeScript quietly ignores as a non-spreadable value, which is essentially what we were seeing the last post (that Null and Undefined values were quietly ignored).
Now, if we run the above code, we get the following console output:
Pretty cool stuff! As you can see, every time we run the ts-node file, we get a randomly-spread result. If these conditions had meaningful variable names, instead of Math.random() calls, I think it would lead to rather elegant, very readable logic.
Want to use code from this post? Check out the license.
Reader Comments
This is great, I had no idea "falsey" objects could be not-spread! Very elegant, inline solution ... whereas other "conditional" approaches are always really ugly!
I've done something similar with Array spread before. It was nice to have this logic inline, but it's ugly, because of the false-condition:
So I'm going to experiment to see if Array-spread exhibits the same falsey-behavior, which would clean this up a bit!
@Scott,
I haven't tested this myself, but I've read that Array-spread is more strict. I think the difference (as I've read) is that Array-spread is more about the "Iterable Interface" where as the Object-spread is more about feature-parity with
Object.assign()
, which I suppose is a lot more forgiving.But, like I said, I haven't tested myself.
Awesome! bbb
I didn't know that
( Math.random() < .5 ) && value2
returns object if left side operand istrue
. Something new every day )@Artem,
Oh yeah, this is one of my favorite features of JavaScript! This type of behavior works with both the
&&
and the||
operator, but in slightly different ways. At the core, both operators return the last evaluated value.So, with the
&&
operator, the last evaluated value is the last one that evaluated to "true"; or, the first one that evaluated to "false":The expression will return the first False value because
&&
"short-circuits" the expression. Meaning, once the runtime hits the Falsey value, it knows that it doesn't have to evaluate the rest of the operands as the overall expression will never be "True" at that point.With the
||
, its the same idea:The
||
operator is particularly helpful for ensuring default values:Here, you are using
a
, unless it evaluates to a Falsey value, in which case you are using"my default value"
as the fallback.Hope you found this interesting.
@Ben,
Thank you! I already used operator
||
before, like it shown in your last example. However this trick with&&
is new for me.@Artem,
Woot, happy to help :D