code: private void checkForOfTypes(NodeTraversal t, Node forOf) {
      Node lhs = forOf.getFirstChild();
      Node iterable = forOf.getSecondChild();
      JSType iterableType = getJSType(iterable);
      JSType actualType;
  
      if (forOf.isForAwaitOf()) {
        Optional<JSType> maybeType =
            validator.expectAutoboxesToIterableOrAsyncIterable(
                iterable,
                iterableType,
                "Can only async iterate over a (non-null) Iterable or AsyncIterable type");
  
        if (!maybeType.isPresent()) {
          // Not iterable or async iterable, error reported by
          // expectAutoboxesToIterableOrAsyncIterable.
          return;
        }
  
        actualType = maybeType.get();
      } else {
        validator.expectAutoboxesToIterable(
            iterable, iterableType, "Can only iterate over a (non-null) Iterable type");
  
        actualType =
            // Convert primitives to their wrapper type and remove null/undefined
            // If iterable is a union type, autoboxes each member of the union.
            iterableType
                .autobox()
                .getTemplateTypeMap()
                .getResolvedTemplateType(typeRegistry.getIterableTemplate());
      }
  
      if (NodeUtil.isNameDeclaration(lhs)) {
        // e.g. get "x" given the VAR in "for (var x of arr) {"
        lhs = lhs.getFirstChild();
      }
      if (lhs.isDestructuringLhs()) {
        // e.g. get `[x, y]` given the VAR in `for (var [x, y] of arr) {`
        lhs = lhs.getFirstChild();
      }
  
      checkCanAssignToWithScope(
          t,
          forOf,
          lhs,
          actualType,
          lhs.getJSDocInfo(),
          "declared type of for-of loop variable does not match inferred type");
    }
docs: Visits the loop variable of a FOR_OF and FOR_AWAIT_OF and verifies the type being assigned to
  it.