Maps API loaded in NextJs component not directly available to instantiated class

I am using the Google Maps API and am working with NextJS and typescript.

I have to instantiate a class used for rendering purposes, but I am getting an error.

My code:

TLDR: loading Map, MapsLibraries and instantiating the Controller class.

Map.tsx

function GoogleMap() {
  const position = { lat: 53.0708031, lng: 12.7569469 };
  const mapId = "test";
  

  return (
    <div className="h-full w-full relative">
      <APIProvider
        apiKey={process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY as string}
      >
        <Map
          defaultCenter={position}
          defaultZoom={16}
          mapId={mapId}
          fullscreenControl={false}
          tilt={0}
          tiltInteractionEnabled={false}
          rotateControl={false}
          mapTypeControl={false}
          mapTypeId="satellite"
        ></Map>
        <Directions />
      </APIProvider>
    </div>
  );
}

function Directions() {
  const map = useMap();
  const coreLibrary = useMapsLibrary("core");
  const markerLibrary = useMapsLibrary("marker");
  const routesLibrary = useMapsLibrary("routes");
  const mapsLibrary = useMapsLibrary("maps");
  const [directionsService, setDirectionsService] =
    useState<google.maps.DirectionsService>();
  const [directionsRenderer, setDirectionsRenderer] = useState<Directions>();

  useEffect(() => {
    if (
      !routesLibrary ||
      !map ||
      !coreLibrary ||
      !markerLibrary ||
      !mapsLibrary ||
      !window.google
    ) {
      return;
    }
    console.log("google", window.google);
    setDirectionsService(new routesLibrary.DirectionsService());

    // --- relevant initialization ----

    setDirectionsRenderer(new Controller(map));
  }, [
    coreLibrary,
    markerLibrary,
    mapsLibrary,
    routesLibrary,
    map,
  ]);

controller.ts (simplified):

 class Controller extends google.maps.OverlayView implements Directions {
         private map;
        constructor(map: google.maps.Map) {
             this.map = map
        }
 }

But this results in Error: “google is undefined”, even though google is defined at the time we are creating our component.

This can be fixed like this:

    // instead of new Controller() you call initialize() in <Directions/>
    function initialize(map: google.maps.Map){
    class Controller extends google.maps.OverlayView implements Directions {
         private map;
        constructor(map: google.maps.Map) {
             this.map = map
        }
     }
     return new Controller(map)
    }

I thought it could be an issue with nextjs seeing this as server side code and compiling it before it has ever seen the client (and no Maps API loaded) , so I marked controller.ts as “use client”, but the issue persists.


Why is that? How are we “loosing” the window.google object?

Is there another workaround for this?

What are the technical details?

Thank you for any help, I am really stuck here.