Destructure object properties inside array for all elements

You can destructure nested objects like this

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Nested_object_and_array_destructuring

let arr = [
  {val:"a"},
  {val:"b"}
];

const [{val: valueOfA}, {val: valueOfB}] = arr

console.log(
  valueOfA, valueOfB
)

Why doesn't let [...{val:res}] = arr; return all values (['a', 'b'])?

You seem to confuse the rest syntax with array comprehensions.

If you assign a value to [someElements, ...someExpression], the value is tested to be iterable and then each element generated by the iterator is assigned to the respective someElements variable. If you use the rest syntax in the destructuring expression, an array is created and the iterator is ran till its end while filling the array with the generated values. Then that array is assigned to the someExpression.

All of these assignment targets can be other destructuring expressions (arbitrarily nested and recursively evaluated), or references to variable or properties.

So if you do let [...{val:res}] = arr, it will create an array and fill that with all the values from the iterator of arr:

let {val:res} = Array.from(arr[Symbol.iterator]())

You can see now why that ends up with undefined, and why using something like [...{length:res}] does yield a result. Another example:

let [{val:res1}, ...{length: res2}] = arr;
console.log(res1) // 'a'
console.log(res2) // 1 (length of `[{val: 'b'}]`)

How can destructuring be used to obtain only the values ['a', 'b']?

Not at all. Use the map method.