src/com/google/javascript/jscomp/TypeCheck.java
/**
   * Emits a warning if we can prove that a property cannot possibly be defined on an object. Note
   * the difference between JS and a strictly statically typed language: we're checking if the
   * property *cannot be defined*, whereas a java compiler would check if the property *can be
   * undefined.
   *
   * <p>This method handles property access in both GETPROPs and object destructuring.
   * Consequentially some of its arguments are optional - the actual object node and the getprop -
   * while others are required.
   *
   * @param objNode the actual node representing the object we're accessing. optional because
   *     destructuring accesses MAY not have an actual object node
   * @param getProp the GETPROP node representing this property access. optional because
   *     destructuring accesses don't have actual getprops.
   */
Emits a warning if we can prove that a property cannot possibly be defined on an object. Note
the difference between JS and a strictly statically typed language: we're checking if the
property *cannot be defined*, whereas a java compiler would check if the property *can be
undefined.

This method handles property access in both GETPROPs and object destructuring.
Consequentially some of its arguments are optional - the actual object node and the getprop
while others are required.

@param objNode the actual node representing the object we're accessing. optional because
destructuring accesses MAY not have an actual object node
@param getProp the GETPROP node representing this property access. optional because
destructuring accesses don't have actual getprops.
Emits a warning if we can prove that a property cannot possibly be defined on an object . Note the difference between JS and a strictly statically typed language : we ' re checking if the property * cannot be defined * whereas a java compiler would check if the property * can be undefined . This method handles property access in both GETPROPs and object destructuring . Consequentially some of its arguments are optional - the actual object node and the getprop while others are required . @param objNode the actual node representing the object we ' re accessing . optional because destructuring accesses MAY not have an actual object node @param getProp the GETPROP node representing this property access . optional because destructuring accesses don ' t have actual getprops .
private void checkPropertyAccess(
      JSType childType,
      NodeTraversal t,
      @Nullable Node getProp,
      JSType propType,
      Node propNode,
      @Nullable Node objNode) {
    String propName = propNode.getString();
    if (propType.isEquivalentTo(typeRegistry.getNativeType(UNKNOWN_TYPE))) {
      childType = childType.autobox();
      ObjectType objectType = ObjectType.cast(childType);
      if (objectType != null) {
        if (!objectType.hasProperty(propName)
            || objectType.isEquivalentTo(typeRegistry.getNativeType(UNKNOWN_TYPE))) {
          if (objectType instanceof EnumType) {
            report(t, getProp != null ? getProp : propNode, INEXISTENT_ENUM_ELEMENT, propName);
          } else {
            checkPropertyAccessHelper(objectType, propNode, objNode, t, getProp, false);
          }
        }
      } else {
        checkPropertyAccessHelper(childType, propNode, objNode, t, getProp, false);
      }
    } else if (childType.isUnionType() && getProp != null && !isLValueGetProp(getProp)) {
      checkPropertyAccessHelper(childType, propNode, objNode, t, getProp, true);
    }
  }
private void checkPropertyAccess ( JSType childType , NodeTraversal t , @ Nullable Node getProp , JSType propType , Node propNode , @ Nullable Node objNode ) { String propName = propNode . getString ( ) ; if ( propType . isEquivalentTo ( typeRegistry . getNativeType ( UNKNOWN_TYPE ) ) ) { childType = childType . autobox ( ) ; ObjectType objectType = ObjectType . cast ( childType ) ; if ( objectType != null ) { if ( ! objectType . hasProperty ( propName ) || objectType . isEquivalentTo ( typeRegistry . getNativeType ( UNKNOWN_TYPE ) ) ) { if ( objectType instanceof EnumType ) { report ( t , getProp != null ? getProp : propNode , INEXISTENT_ENUM_ELEMENT , propName ) ; } else { checkPropertyAccessHelper ( objectType , propNode , objNode , t , getProp , false ) ; } } } else { checkPropertyAccessHelper ( childType , propNode , objNode , t , getProp , false ) ; } } else if ( childType . isUnionType ( ) && getProp != null && ! isLValueGetProp ( getProp ) ) { checkPropertyAccessHelper ( childType , propNode , objNode , t , getProp , true ) ; } }
Emits a warning if we can prove that a property cannot possibly be defined on an object.
Emits a warning if we can prove that a property cannot possibly be defined on an object .
// We special-case object types so that checks on enums can be // much stricter, and so that we can use hasProperty (which is much // faster in most cases). // NOTE: strict property assignment checks are done on assignment.