tl;dr: I've found that sometimes returning false
in a proxy's set() trap doesn't trigger any TypeError
, and sometimes it does. Why does this happen?
As far as I understand, set() traps in a proxy must return either true
or false
to denote whether a writing operation was allowed or not. If false
is returned, then that should trigger a TypeError
.
However, this doesn't always happen. Take a look at these two examples:
Example 1 (invalid, but no TypeError)
let page = { currentPage: "Home" };
page = new Proxy(page, {
set(target, property, value) {
if (typeof value !== "string") return false;
//... additional validation logic could be here
target[property] = value;
return true;
}
});
// Attempt an invalid operation:
page.currentPage = 123;
console.log(page.currentPage); // currentPage is still "Home"
// (writing didn't work, but it didn't trigger any TypeError to let me know!)
Example 2 (invalid, and throws TypeError) (example taken from javascript.info)
let numbers = [];
numbers = new Proxy(numbers, { // (*)
set(target, property, value) { // to intercept property writing
if (typeof val == 'number') {
target[prop] = val;
return true;
} else {
return false;
}
}
});
numbers.push(1); // added successfully
numbers.push(2); // added successfully
console.log("Length is: " + numbers.length); // 2
// Attempt an invalid operation:
numbers.push("test"); // TypeError ('set' on proxy returned false)
alert("This line is never reached (error in the line above)");
Invalid set operations don't work (as expected), but why do I sometimes get a TypeError and sometimes not? Ideally, I'd like to always get an error so that I can quickly spot and correct my mistakes. Is the only workaround to manually throw an error whenever I return false in the set() trap?
Thank you very much in advance for any help or insight.
Returning
false
from aset
trap will only trigger an error when the code that does the assignment runs in strict mode. In non-strict mode afalse
prevents the assignment but without an error.In your first piece of code the code runs in non-strict mode only. If you modify it to be strict, you get a TypeError:
Different functions or methods might be running either strict mode or not:
In the second block of code it is the
.push()
method that does the writing. That method apparently runs in strict mode, which is why there is a TypeError when it attempts to write to the array index.All classes (and other ES6+ constructs like generators, modules, etc) are automatically in strict mode:
The array is considered a class, hence why its methods are strict.