@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 totsconfig.json:
{
"compilerOptions": {
"types": ["google.maps"]
}
}
Error: Type ‘X’ is not assignable to type ‘Library’
Solution: Use the correct library names from theLibrary 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