Validation with “set” trap

Let’s say we want an array exclusively for numbers. If a value of another type is added, there should be an error.
The set trap triggers when a property is written.
set(target, property, value, receiver):

  • target – is the target object, the one passed as the first argument to new Proxy,
  • property – property name,
  • value – property value,
  • receiver – similar to get trap, matters only for setter properties.

The set trap should return true if setting is successful, and false otherwise (triggers TypeError).
Let’s use it to validate new values:

  1. let numbers = [];
  2. numbers = new Proxy(numbers, { // (*)
  3. set(target, prop, val) { // to intercept property writing
  4. if (typeof val == 'number') {
  5. target[prop] = val;
  6. return true;
  7. } else {
  8. return false;
  9. }
  10. }
  11. });
  12. numbers.push(1); // added successfully
  13. numbers.push(2); // added successfully
  14. alert("Length is: " + numbers.length); // 2
  15. numbers.push("test"); // TypeError ('set' on proxy returned false)
  16. alert("This line is never reached (error in the line above)");

Please note: the built-in functionality of arrays is still working! Values are added by push. The length property auto-increases when values are added. Our proxy doesn’t break anything.
We don’t have to override value-adding array methods like push and unshift, and so on, to add checks in there, because internally they use the [[Set]] operation that’s intercepted by the proxy.
So the code is clean and concise.
Don’t forget to return true
As said above, there are invariants to be held.
For set, it must return true for a successful write.
If we forget to do it or return any falsy value, the operation triggers TypeError.