-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Description
Copied from #19931(comment)
I guess as of #19831 I could simplify this using optional chaining:
wrapperNode.current &&
wrapperNode.current.contains( document.activeElement )
// =>
wrapperNode.current?.contains( document.activeElement )What's interesting to me is looking at the other, negated instance of this condition, I sense there's going to be a very common pitfall associated with optional chaining:
gutenberg/packages/block-editor/src/components/link-control/index.js
Lines 112 to 113 in 5b72b3a
| wrapperNode.current && | |
| ! wrapperNode.current.contains( document.activeElement ) |
If someone treats optional chaining as a way to get to the value by any means necessary, it might be easy to overlook that negating would produce true if the optional chaining aborts early:
const wrapperNode = { current: undefined };
! wrapperNode.current?.contains( document.activeElement );
// true😯 It's definitely not the expected result.
It seems like in the same category of issues we restrict with this ESLint rule:
https://eslint.org/docs/rules/no-unsafe-negation
I could imagine some improvement to that rule which forbids negation of optional chains.
! wrapperNode.current?.contains() is ! ( wrapperNode.current && wrapperNode.current.contains() ).
It's not wrapperNode.current && ! wrapperNode.current.contains().
We need an eslint rule to help us to not fall into this pitfall.