TypeError: window.initMap is not a function

Removing =initMap worked for me:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback"></script>

Actually the error is being generated by the initMap in the Google's api script

 <script async defer
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

so basically when the Google Map API is loaded then the initMap function is executed. If you don't have an initMap function, then the initMap is not a function error is generated.

So basically what you have to do is one of the following options:

  1. to create an initMap function
  2. replace the callback function with one of your own that created for the same purpose but named it something else
  3. replace the &callback=angular.noop if you just want an empty function() (only if you use angular)

My explanation of this problem:

The .....&callback=initMap" async defer></script> makes that script load async (in parallel with DOM) and after load - execute initMap function. NOTICE that initMap() in global scope! We can't declare our initMap() after google's script because it should already be at the moment of finish async load. Although we can't load our script before this, because we need google's function to execute ours. This is like vicious circle.

Three solutions:

1'st and worst: make google's script load synchronously

  1. remove async defer
  2. remove &callback=initMap in src attribute
  3. put <script tag with your code after google's script

2'nd and best: just do this =)

  1. leave .....&callback=initMap" async defer></script> as is
  2. and put google's <script tag after your script
  3. write in your script

    function initMap() {} // now it IS a function and it is in global
    
    $(() => {
      initMap = function() {
        // your code like...
        var map = new google.maps.Map(document.getElementById('map'), {/*your code*/});
        // and other stuff...
      }
    })
    

    this allow you load google's script async and run yours just after that

3'rd and strange: it will work... some times =)

  1. do same but simply write in global scope

    function initMap() {
      // your code
    }
    

    and if you write it in global scope, that will work regardless of what which code loads faster, your (sync) or google's (async). More often your wins