Skip to main content
The @react-google-maps/api library is built with TypeScript and provides complete type definitions for all components, hooks, and Google Maps API interfaces.

Type Definitions

The library exports TypeScript types for all components and utilities. All types are automatically available when you import from the library.

Core Types

UseJsApiLoader Types

import type { UseLoadScriptOptions } from '@react-google-maps/api';

type UseLoadScriptOptions = {
  googleMapsApiKey: string;
  googleMapsClientId?: string | undefined;
  language?: string | undefined;
  region?: string | undefined;
  libraries?: Libraries | undefined;
  channel?: string | undefined;
  mapIds?: string[] | undefined;
  authReferrerPolicy?: 'origin' | undefined;
  version?: string;
  id?: string | undefined;
  nonce?: string | undefined;
  preventGoogleFontsLoading?: boolean | undefined;
};

// Return type
type UseJsApiLoaderReturn = {
  isLoaded: boolean;
  loadError: Error | undefined;
};

LoadScript Types

import type { LoadScriptProps } from '@react-google-maps/api';

type LoadScriptProps = {
  children?: ReactNode | undefined;
  id: string;
  nonce?: string | undefined;
  loadingElement?: ReactNode;
  onLoad?: () => void;
  onError?: (error: Error) => void;
  onUnmount?: () => void;
  preventGoogleFontsLoading?: boolean;
  googleMapsApiKey: string;
  googleMapsClientId?: string | undefined;
  language?: string | undefined;
  region?: string | undefined;
  libraries?: Libraries | undefined;
  channel?: string | undefined;
  mapIds?: string[] | undefined;
  authReferrerPolicy?: 'origin' | undefined;
  version?: string;
};

GoogleMap Types

import type { GoogleMapProps } from '@react-google-maps/api';

type GoogleMapProps = {
  children?: ReactNode | undefined;
  id?: string | undefined;
  mapContainerStyle?: CSSProperties | undefined;
  mapContainerClassName?: string | undefined;
  options?: google.maps.MapOptions | undefined;
  extraMapTypes?: google.maps.MapType[] | undefined;
  center?: google.maps.LatLng | google.maps.LatLngLiteral | undefined;
  clickableIcons?: boolean | undefined;
  heading?: number | undefined;
  mapTypeId?: string | undefined;
  streetView?: google.maps.StreetViewPanorama | undefined;
  tilt?: number | undefined;
  zoom?: number | undefined;
  
  // Event handlers
  onClick?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onDblClick?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onDrag?: (() => void) | undefined;
  onDragEnd?: (() => void) | undefined;
  onDragStart?: (() => void) | undefined;
  onMouseMove?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onMouseOut?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onMouseOver?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onMouseDown?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onMouseUp?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  onRightClick?: ((e: google.maps.MapMouseEvent) => void) | undefined;
  
  // Map state change events
  onMapTypeIdChanged?: (() => void) | undefined;
  onTilesLoaded?: (() => void) | undefined;
  onBoundsChanged?: (() => void) | undefined;
  onCenterChanged?: (() => void) | undefined;
  onHeadingChanged?: (() => void) | undefined;
  onIdle?: (() => void) | undefined;
  onProjectionChanged?: (() => void) | undefined;
  onResize?: (() => void) | undefined;
  onTiltChanged?: (() => void) | undefined;
  onZoomChanged?: (() => void) | undefined;
  
  // Lifecycle
  onLoad?: ((map: google.maps.Map) => void | Promise<void>) | undefined;
  onUnmount?: ((map: google.maps.Map) => void | Promise<void>) | undefined;
};

Libraries Type

import type { Libraries } from '@react-google-maps/api';
import type { Library } from '@googlemaps/js-api-loader';

type Libraries = Library[];

// Library is a union type:
type Library = 
  | 'core'
  | 'maps'
  | 'places'
  | 'geocoding'
  | 'routes'
  | 'marker'
  | 'geometry'
  | 'elevation'
  | 'streetView'
  | 'journeySharing'
  | 'drawing'
  | 'visualization';

Using Types in Your Application

Basic Typed Component

import { GoogleMap, useJsApiLoader } from '@react-google-maps/api';
import type { GoogleMapProps } from '@react-google-maps/api';
import { FC } from 'react';

const mapContainerStyle: React.CSSProperties = {
  width: '100%',
  height: '400px',
};

const center: google.maps.LatLngLiteral = {
  lat: 40.7128,
  lng: -74.0060,
};

const Map: FC = () => {
  const { isLoaded, loadError } = useJsApiLoader({
    googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!,
  });

  if (loadError) return <div>Error loading maps</div>;
  if (!isLoaded) return <div>Loading maps</div>;

  return (
    <GoogleMap
      mapContainerStyle={mapContainerStyle}
      center={center}
      zoom={10}
    />
  );
};

export default Map;

Typed Event Handlers

import { GoogleMap } from '@react-google-maps/api';
import { useCallback } from 'react';

function TypedMapEvents() {
  const handleClick = useCallback((e: google.maps.MapMouseEvent) => {
    if (e.latLng) {
      const lat: number = e.latLng.lat();
      const lng: number = e.latLng.lng();
      console.log(`Clicked at: ${lat}, ${lng}`);
    }
  }, []);

  const handleLoad = useCallback((map: google.maps.Map) => {
    const bounds: google.maps.LatLngBounds = new google.maps.LatLngBounds();
    bounds.extend({ lat: 40.7128, lng: -74.0060 });
    bounds.extend({ lat: 34.0522, lng: -118.2437 });
    map.fitBounds(bounds);
  }, []);

  return (
    <GoogleMap
      onClick={handleClick}
      onLoad={handleLoad}
    />
  );
}

Typed Map Options

import { GoogleMap } from '@react-google-maps/api';

const mapOptions: google.maps.MapOptions = {
  disableDefaultUI: true,
  zoomControl: true,
  streetViewControl: false,
  mapTypeControl: true,
  fullscreenControl: true,
  clickableIcons: false,
  gestureHandling: 'greedy',
  mapTypeId: 'roadmap',
  styles: [
    {
      featureType: 'water',
      elementType: 'geometry',
      stylers: [{ color: '#193341' }],
    },
  ],
  restriction: {
    latLngBounds: {
      north: 85,
      south: -85,
      west: -180,
      east: 180,
    },
    strictBounds: false,
  },
  minZoom: 3,
  maxZoom: 18,
};

function TypedMapOptions() {
  return <GoogleMap options={mapOptions} />;
}

Typed Libraries Array

import { useJsApiLoader } from '@react-google-maps/api';
import type { Libraries } from '@react-google-maps/api';

// Define as const to ensure stable reference
const libraries: Libraries = ['places', 'geometry', 'drawing'];

function TypedLoader() {
  const { isLoaded } = useJsApiLoader({
    googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!,
    libraries,
  });

  return isLoaded ? <div>Loaded</div> : <div>Loading...</div>;
}

Typed Map Reference

import { GoogleMap } from '@react-google-maps/api';
import { useRef, useCallback } from 'react';

function MapWithRef() {
  const mapRef = useRef<google.maps.Map | null>(null);

  const handleLoad = useCallback((map: google.maps.Map) => {
    mapRef.current = map;
  }, []);

  const panToLocation = useCallback((location: google.maps.LatLngLiteral) => {
    if (mapRef.current) {
      mapRef.current.panTo(location);
    }
  }, []);

  const getCurrentZoom = useCallback((): number | undefined => {
    return mapRef.current?.getZoom();
  }, []);

  const getCurrentBounds = useCallback((): google.maps.LatLngBounds | undefined => {
    return mapRef.current?.getBounds();
  }, []);

  return (
    <>
      <button onClick={() => panToLocation({ lat: 40.7128, lng: -74.0060 })}>
        Pan to NYC
      </button>
      <GoogleMap onLoad={handleLoad} />
    </>
  );
}

Google Maps API Types

The library relies on the @types/google.maps package for Google Maps API type definitions. These are automatically included as dependencies.

Common Google Maps Types

// Coordinate types
type LatLng = google.maps.LatLng;
type LatLngLiteral = google.maps.LatLngLiteral;
type LatLngBounds = google.maps.LatLngBounds;
type LatLngBoundsLiteral = google.maps.LatLngBoundsLiteral;

// Map types
type Map = google.maps.Map;
type MapOptions = google.maps.MapOptions;
type MapTypeId = google.maps.MapTypeId;
type MapMouseEvent = google.maps.MapMouseEvent;

// Marker types
type Marker = google.maps.Marker;
type MarkerOptions = google.maps.MarkerOptions;

// Geometry types
type Point = google.maps.Point;
type Size = google.maps.Size;

// Events
type MapsEventListener = google.maps.MapsEventListener;

Using Google Maps Types

import { GoogleMap, Marker } from '@react-google-maps/api';
import { useState } from 'react';

function TypedMarkers() {
  const [markers, setMarkers] = useState<google.maps.LatLngLiteral[]>([]);

  const handleMapClick = (e: google.maps.MapMouseEvent) => {
    if (e.latLng) {
      setMarkers((current) => [
        ...current,
        e.latLng.toJSON() as google.maps.LatLngLiteral,
      ]);
    }
  };

  const handleMarkerClick = (marker: google.maps.LatLngLiteral) => {
    setMarkers((current) => 
      current.filter((m) => m.lat !== marker.lat || m.lng !== marker.lng)
    );
  };

  return (
    <GoogleMap onClick={handleMapClick}>
      {markers.map((marker, index) => (
        <Marker
          key={index}
          position={marker}
          onClick={() => handleMarkerClick(marker)}
        />
      ))}
    </GoogleMap>
  );
}

Advanced Patterns

Generic Map Component

import { GoogleMap } from '@react-google-maps/api';
import type { GoogleMapProps } from '@react-google-maps/api';
import { FC } from 'react';

interface MapWrapperProps extends Omit<GoogleMapProps, 'mapContainerStyle'> {
  height?: string | number;
  width?: string | number;
}

const MapWrapper: FC<MapWrapperProps> = ({
  height = '400px',
  width = '100%',
  ...props
}) => {
  return (
    <GoogleMap
      mapContainerStyle={{ height, width }}
      {...props}
    />
  );
};

export default MapWrapper;

Typed Custom Hook

import { GoogleMap, useGoogleMap } from '@react-google-maps/api';
import { useEffect, useState } from 'react';

function useMapBounds() {
  const map = useGoogleMap();
  const [bounds, setBounds] = useState<google.maps.LatLngBounds | null>(null);

  useEffect(() => {
    if (!map) return;

    const listener = map.addListener('bounds_changed', () => {
      const newBounds = map.getBounds();
      if (newBounds) {
        setBounds(newBounds);
      }
    });

    return () => {
      google.maps.event.removeListener(listener);
    };
  }, [map]);

  return bounds;
}

function MapWithBounds() {
  const bounds = useMapBounds();

  return (
    <div>
      {bounds && (
        <div>
          NE: {bounds.getNorthEast().toJSON().lat.toFixed(4)},
          {bounds.getNorthEast().toJSON().lng.toFixed(4)}
        </div>
      )}
    </div>
  );
}

function App() {
  return (
    <GoogleMap>
      <MapWithBounds />
    </GoogleMap>
  );
}

Type-Safe Configuration

import type { UseLoadScriptOptions, Libraries } from '@react-google-maps/api';

interface MapConfig {
  apiKey: string;
  libraries: Libraries;
  defaultCenter: google.maps.LatLngLiteral;
  defaultZoom: number;
  mapOptions: google.maps.MapOptions;
}

const mapConfig: MapConfig = {
  apiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!,
  libraries: ['places', 'geometry'],
  defaultCenter: { lat: 40.7128, lng: -74.0060 },
  defaultZoom: 10,
  mapOptions: {
    disableDefaultUI: true,
    zoomControl: true,
    streetViewControl: false,
  },
};

export function getLoaderOptions(): UseLoadScriptOptions {
  return {
    googleMapsApiKey: mapConfig.apiKey,
    libraries: mapConfig.libraries,
  };
}

export function getMapProps(): {
  center: google.maps.LatLngLiteral;
  zoom: number;
  options: google.maps.MapOptions;
} {
  return {
    center: mapConfig.defaultCenter,
    zoom: mapConfig.defaultZoom,
    options: mapConfig.mapOptions,
  };
}

Type Inference

The library provides excellent type inference for most use cases:
import { GoogleMap, useGoogleMap } from '@react-google-maps/api';

function InferredTypes() {
  const { isLoaded, loadError } = useJsApiLoader({
    googleMapsApiKey: 'KEY',
  });
  // isLoaded is inferred as boolean
  // loadError is inferred as Error | undefined

  const map = useGoogleMap();
  // map is inferred as google.maps.Map | null

  const handleClick = (e: google.maps.MapMouseEvent) => {
    const latLng = e.latLng;
    // latLng is inferred as google.maps.LatLng | null | undefined

    if (latLng) {
      const lat = latLng.lat();
      const lng = latLng.lng();
      // lat and lng are inferred as number
    }
  };

  return <GoogleMap onClick={handleClick} />;
}

Common Type Errors and Solutions

Error: Property ‘google’ does not exist

Solution: Install @types/google.maps:
npm install --save-dev @types/google.maps

Error: Cannot find namespace ‘google’

Solution: Add types to tsconfig.json:
{
  "compilerOptions": {
    "types": ["google.maps"]
  }
}

Error: Type ‘X’ is not assignable to type ‘Library’

Solution: Use the correct library names from the Library union type:
// ❌ Incorrect
const libraries = ['place']; // Typo

// ✅ Correct
const libraries: Libraries = ['places'];

Next Steps

SSR Support

Learn about server-side rendering

Components

Explore typed components

Build docs developers (and LLMs) love