code: Node tryOptimizeObjectPattern(Node pattern) {
      checkArgument(pattern.isObjectPattern(), pattern);
  
      if (pattern.hasChildren() && pattern.getLastChild().isRest()) {
        // don't remove any elements in `const {f: [], ...rest} = obj` because that affects what's
        // assigned to `rest`. only the last element can be object rest.
        return pattern;
      }
  
      // remove trailing EMPTY nodes and empty destructuring patterns
      for (Node child = pattern.getFirstChild(); child != null; ) {
        Node key = child;
        child = key.getNext(); // don't put this in the for loop since we might remove `child`
  
        if (!key.isStringKey()) {
          // don't try to remove rest or computed properties, since they might have side effects
          continue;
        }
        if (isRemovableDestructuringTarget(key.getOnlyChild())) {
          // e.g. `const {f: {}} = obj;`
          key.detach();
          reportChangeToEnclosingScope(pattern);
        }
      }
      return pattern;
    }
docs: Removes string keys with an empty pattern as their child