Not keyword operators

I'll make this quick.

What we do:

// Keyword operators
Infinity instanceof Object // false
"length" in [] // true

// To check for not-instanceof or not-in
!(Infinity instanceof Object) // true
!("length" in []) // false

What I propose:

Infinity !instanceof Object // true
"length" !in [] // false

In terms of readability, I'd say it's easier to follow. It also reduces the need for extra parentheses when doing if(!(condition)){}.

What do you think?

5 Likes

Great idea, this syntax is possibly ambiguous with TypeScript’s non-null assertion operator though.

I'm not sure this is quite common enough to merit new syntax for it.

I write code like this all the time.

try {
  ...
} catch (err) {
  if (!(err instanceof Whatever)) throw err
  ...
}

The (!(...)) thing is pretty gross.

There are other languages who provide support for this sort of syntax, like Python.

if x not in my_array:
  do_whatever()

However, I also understand that delegates are hoping to eventually improve JavaScript's catch syntax. When this happens, my use for instanceof will likely go way down. The "in" operator doesn't seem to be used a ton either, partially because many people treat a property explicitly set to undefined, and missing properties, as the same. The "in" operator will distinguish between these two scenarios, while syntax such as if (obj.maybeMissingProperty != null) does not. So, I can also see @claudiameadows's point.

going off-topic, but your try {...} catch (e) { if (...) throw e } design-pattern is PITA to write test-coverage for.

a more coverage-friendly design-pattern is with helper assertOrThrow() -- a reusable-function whose only ux-purpose is boosting code-coverage for above-stated and similar error-handling scenarios.

+function assertOrThrow(condition, message) {
+  // This function will throw <message> if <condition> is falsy.
+  if (!condition) {
+    throw (
+      (!message || typeof message === "string")
+      // if message is string, convert to Error and throw
+      ? new Error(message)
+      // if message is object, assume error-object and throw directly
+      : message
+    );
+  }
+}
 
 try {
   ...
 } catch (err) {
-  if (!(err instanceof Whatever)) throw err
+  // use helper-function to avoid writing tedious code-coverage
+  // for the if-branch
+  assertOrThrow(err instanceof Whatever, err);
   ...
 }