<subjective>That's ... not a good example of that feature. :-D</subjective> It works because the rest element creates a new array, and then the object destructuring pattern { pop, push } picks out those properties from that new array (not the original array).
The closest I can come to a useful example is if you want to know how many additional elements there were beyond the ones you wanted, but you don't want/need the actual array of them:
let a, b, length;
[a, b, ...{ length }] = [1, 2];
console.log(length); // 0, there were no extra elements
[a, b, ...{ length }] = [1, 2, 3];
console.log(length); // 1, there was one extra
[a, b, ...{ length }] = [1, 2, 3, 4];
console.log(length); // 2, there were two extra
...but I think the fact is that while you can use object/array destructuring on the rest element because it falls out naturally from the way destructuring patterns work, it's unlikely to be all that useful.
I should note that in the more general case, using object destructuring on an array can indeed be useful, just probably not when applied to a rest element. It's especially useful for augmented arrays like the one you get from RegExp.prototype.exec, which includes not just the array elements for the match and any capture group values, but also index (where the match occurred), input, groups, and indices. You might want those. Object destructuring on an array lets you get the specific elements you want as well as non-element properties, for example:
const str = "an example string";
const match = /example/.exec(str);
if (match) {
const {0: matched, index } = match;
console.log(`Matched ${JSON.stringify(matched)} at index ${index}.`);
}
It's also useful for picking out just a couple of elements from the middle:
const array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
const {2: two, 7: seven} = array;
console.log(`two = ${two}, seven = ${seven}`);