third_party/closure-compiler/src/src/com/google/javascript/jscomp/TypeInference.java
/**
   * For functions that use template types, specialize the function type for the call target based
   * on the call-site specific arguments. Specifically, this enables inference to set the type of
   * any function literal parameters based on these inferred types.
   */
For functions that use template types, specialize the function type for the call target based
on the call-site specific arguments. Specifically, this enables inference to set the type of
any function literal parameters based on these inferred types.
For functions that use template types specialize the function type for the call target based on the call - site specific arguments . Specifically this enables inference to set the type of any function literal parameters based on these inferred types .
private boolean inferTemplatedTypesForCall(Node n, FunctionType fnType, FlowScope scope) {
    ImmutableList<TemplateType> keys = fnType.getTemplateTypeMap().getTemplateKeys();
    if (keys.isEmpty()) {
      return false;
    }
    Map<TemplateType, JSType> bindings = inferTemplateTypesFromParameters(fnType, n, scope);
    Map<TemplateType, JSType> inferred = Maps.newIdentityHashMap();
    for (TemplateType key : keys) {
      inferred.put(key, bindings.getOrDefault(key, unknownType));
    }
    inferred.replaceAll((k, v) -> v.isSubtypeOf(k.getBound()) ? v : k.getBound());
     using the type transformations
    Map<TemplateType, JSType> typeTransformations =
        evaluateTypeTransformations(keys, inferred, scope);
    if (typeTransformations != null) {
      inferred.putAll(typeTransformations);
    }
    TemplateTypeReplacer replacer = TemplateTypeReplacer.forInference(registry, inferred);
    Node callTarget = n.getFirstChild();
    FunctionType replacementFnType = fnType.visit(replacer).toMaybeFunctionType();
    checkNotNull(replacementFnType);
    callTarget.setJSType(replacementFnType);
    n.setJSType(replacementFnType.getReturnType());
    return replacer.hasMadeReplacement();
  }
private boolean inferTemplatedTypesForCall ( Node n , FunctionType fnType , FlowScope scope ) { ImmutableList < TemplateType > keys = fnType . getTemplateTypeMap ( ) . getTemplateKeys ( ) ; if ( keys . isEmpty ( ) ) { return false ; } Map < TemplateType , JSType > bindings = inferTemplateTypesFromParameters ( fnType , n , scope ) ; Map < TemplateType , JSType > inferred = Maps . newIdentityHashMap ( ) ; for ( TemplateType key : keys ) { inferred . put ( key , bindings . getOrDefault ( key , unknownType ) ) ; } inferred . replaceAll ( ( k , v ) -> v . isSubtypeOf ( k . getBound ( ) ) ? v : k . getBound ( ) ) ; Map < TemplateType , JSType > typeTransformations = evaluateTypeTransformations ( keys , inferred , scope ) ; if ( typeTransformations != null ) { inferred . putAll ( typeTransformations ) ; } TemplateTypeReplacer replacer = TemplateTypeReplacer . forInference ( registry , inferred ) ; Node callTarget = n . getFirstChild ( ) ; FunctionType replacementFnType = fnType . visit ( replacer ) . toMaybeFunctionType ( ) ; checkNotNull ( replacementFnType ) ; callTarget . setJSType ( replacementFnType ) ; n . setJSType ( replacementFnType . getReturnType ( ) ) ; return replacer . hasMadeReplacement ( ) ; }
For functions that use template types, specialize the function type for the call target based
 on the call-site specific arguments.
For functions that use template types specialize the function type for the call target based on the call - site specific arguments .
// Try to infer the template types // If the inferred type doesn't satisfy the template bound, swap to using the bound. This // ensures errors will be reported in type-checking. // Try to infer the template types using the type transformations // Replace all template types. If we couldn't find a replacement, we // replace it with UNKNOWN.