Type System
Complete reference for TypeScript types and interfaces in the Route Optimization Map library.
Overview
All packages are written in TypeScript and provide comprehensive type definitions. This guide covers the core types used across the library.
Core Types
LatLng
Geographic coordinates (latitude and longitude).
interface LatLng {
lat: number; // Latitude: -90 to 90
lng: number; // Longitude: -180 to 180
}Example:
const bangkok: LatLng = {
lat: 13.7563,
lng: 100.5018,
};Stop
A single location on a route.
interface Stop {
id: string;
location: LatLng;
name?: string;
address?: string;
duration?: number;
metadata?: Record<string, any>;
}Example:
const deliveryStop: Stop = {
id: 'delivery-001',
location: { lat: 13.7563, lng: 100.5018 },
name: 'Customer A',
address: '123 Sukhumvit Road',
duration: 15, // minutes
metadata: {
orderId: 'ORD-12345',
priority: 'high',
},
};Route
A sequence of stops to visit.
interface Route {
stops: Stop[];
options?: RouteOptions;
}Example:
const deliveryRoute: Route = {
stops: [
{ id: '1', location: { lat: 13.7563, lng: 100.5018 } },
{ id: '2', location: { lat: 13.7467, lng: 100.5352 } },
],
options: {
polylineOptions: {
strokeColor: '#FF0000',
strokeWeight: 6,
},
},
};RouteOptions
Customization options for route rendering.
interface RouteOptions {
polylineOptions?: PolylineOptions;
markerOptions?: MarkerOptions;
fitBounds?: boolean;
}
interface PolylineOptions {
strokeColor?: string;
strokeOpacity?: number;
strokeWeight?: number;
geodesic?: boolean;
}
interface MarkerOptions {
showLabels?: boolean;
labelColor?: string;
startMarker?: MarkerConfig;
endMarker?: MarkerConfig;
stopMarker?: MarkerConfig;
}
interface MarkerConfig {
icon?: string | MarkerIcon;
label?: string | MarkerLabel;
}Example:
const options: RouteOptions = {
polylineOptions: {
strokeColor: '#4CAF50',
strokeOpacity: 0.8,
strokeWeight: 5,
geodesic: true,
},
markerOptions: {
showLabels: true,
labelColor: '#FFFFFF',
startMarker: {
icon: '/icons/start.png',
label: 'START',
},
},
fitBounds: true,
};Map Types
MapConfig
Configuration for map initialization.
interface MapConfig {
apiKey: string;
center?: LatLng;
zoom?: number;
mapTypeId?: 'roadmap' | 'satellite' | 'hybrid' | 'terrain';
styles?: MapStyle[];
restriction?: MapRestriction;
gestureHandling?: 'cooperative' | 'greedy' | 'none' | 'auto';
}Example:
const mapConfig: MapConfig = {
apiKey: 'YOUR_API_KEY',
center: { lat: 13.7563, lng: 100.5018 },
zoom: 12,
mapTypeId: 'roadmap',
gestureHandling: 'cooperative',
};MapBounds
Geographic boundaries.
interface MapBounds {
north: number;
south: number;
east: number;
west: number;
}Example:
const thailandBounds: MapBounds = {
north: 20.5,
south: 5.5,
east: 106.0,
west: 97.0,
};Optimization Types
OptimizationRequest
Request for route optimization.
interface OptimizationRequest {
shipments: Shipment[];
vehicles: OptimizationVehicle[];
globalStartTime?: string;
globalEndTime?: string;
searchMode?: 'RETURN_FAST' | 'CONSUME_ALL_AVAILABLE_TIME';
}
interface Shipment {
id: string;
pickupLocation?: OptimizationLocation | OptimizationLocation[];
deliveryLocation?: OptimizationLocation | OptimizationLocation[];
loadDemands?: Record<string, number>;
pickupTimeWindows?: TimeWindow[];
deliveryTimeWindows?: TimeWindow[];
}
interface OptimizationLocation {
latitude: number;
longitude: number;
}
interface OptimizationVehicle {
id: string;
startLocation?: OptimizationLocation;
endLocation?: OptimizationLocation;
loadLimits?: LoadLimit[];
costPerKilometer?: number;
costPerHour?: number;
travelMode?: 'DRIVING' | 'WALKING' | 'BICYCLING';
}
interface TimeWindow {
startTime: string; // ISO 8601 format
endTime: string;
}
interface LoadLimit {
type: string;
maxLoad?: number;
softMaxLoad?: number;
costPerUnitAboveSoftMax?: number;
}Example:
const optimizationRequest: OptimizationRequest = {
shipments: [
{
id: 'shipment-1',
deliveryLocation: {
latitude: 13.7563,
longitude: 100.5018,
},
loadDemands: { weight: 50 },
deliveryTimeWindows: [
{
startTime: '2025-12-12T09:00:00Z',
endTime: '2025-12-12T17:00:00Z',
},
],
},
],
vehicles: [
{
id: 'vehicle-1',
startLocation: {
latitude: 13.7563,
longitude: 100.5018,
},
loadLimits: [
{
type: 'weight',
maxLoad: 1000,
},
],
travelMode: 'DRIVING',
},
],
searchMode: 'RETURN_FAST',
};OptimizationResponse
Response from route optimization.
interface OptimizationResponse {
success: boolean;
routes?: OptimizedRoute[];
metrics?: OptimizationMetrics;
statistics?: OptimizationStatistics;
error?: string;
}
interface OptimizedRoute {
vehicleId: string;
stops?: OptimizedStop[];
metrics?: RouteMetrics;
}
interface OptimizedStop {
shipmentId?: string;
location?: OptimizationLocation;
arrivalTime?: string;
departureTime?: string;
loadAfterStop?: Record<string, number>;
}
interface OptimizationMetrics {
totalDistance?: number;
totalDuration?: number;
totalCost?: number;
}
interface OptimizationStatistics {
usedVehicleCount: number;
earliestVehicleStartTime?: string;
latestVehicleEndTime?: string;
}Example:
const response: OptimizationResponse = {
success: true,
routes: [
{
vehicleId: 'vehicle-1',
stops: [
{
shipmentId: 'shipment-1',
location: { latitude: 13.7563, longitude: 100.5018 },
arrivalTime: '2025-12-12T09:30:00Z',
departureTime: '2025-12-12T09:45:00Z',
},
],
metrics: {
distance: 15.5,
duration: 1800,
},
},
],
metrics: {
totalDistance: 15.5,
totalDuration: 1800,
totalCost: 250,
},
};Framework-Specific Types
React Types
// useRouteMap
interface UseRouteMapOptions extends MapConfig {
onError?: (error: Error) => void;
}
interface UseRouteMapReturn {
mapRef: RefObject<HTMLDivElement>;
map: google.maps.Map | null;
isReady: boolean;
renderRoute: (route: Route) => void;
clearRoute: () => void;
addMarker: (location: LatLng, options?: MarkerOptions) => void;
removeMarker: (id: string) => void;
clearMarkers: () => void;
}
// useMapControls
interface UseMapControlsReturn {
center: LatLng | null;
zoom: number | null;
bounds: MapBounds | null;
setCenter: (location: LatLng) => void;
setZoom: (zoom: number) => void;
fitBounds: (bounds: MapBounds) => void;
}
// useRouteOptimization
interface UseRouteOptimizationResult {
status: OptimizationStatus;
data: OptimizationResponse | null;
error: string | null;
isLoading: boolean;
isSuccess: boolean;
isError: boolean;
optimize: (request: OptimizationRequest) => Promise<OptimizationResponse>;
reset: () => void;
reinitialize: (config: RouteCalculatorConfig) => Promise<void>;
}
type OptimizationStatus = 'idle' | 'initializing' | 'optimizing' | 'success' | 'error';Vue Types
// useRouteMap
interface UseRouteMapOptions extends MapConfig {
mapElement: Ref<HTMLDivElement | undefined>;
onError?: (error: Error) => void;
}
interface UseRouteMapReturn {
map: Ref<google.maps.Map | null>;
isReady: Ref<boolean>;
renderRoute: (route: Route) => void;
clearRoute: () => void;
addMarker: (location: LatLng, options?: MarkerOptions) => void;
removeMarker: (id: string) => void;
clearMarkers: () => void;
}
// useMapControls
interface UseMapControlsReturn {
center: Ref<LatLng | null>;
zoom: Ref<number | null>;
bounds: Ref<MapBounds | null>;
setCenter: (location: LatLng) => void;
setZoom: (zoom: number) => void;
fitBounds: (bounds: MapBounds) => void;
}
// useRouteOptimization
interface UseRouteOptimizationResult {
status: Ref<OptimizationStatus>;
data: Ref<OptimizationResponse | null>;
error: Ref<string | null>;
isLoading: Readonly<Ref<boolean>>;
isSuccess: Readonly<Ref<boolean>>;
isError: Readonly<Ref<boolean>>;
optimize: (request: OptimizationRequest) => Promise<OptimizationResponse>;
reset: () => void;
reinitialize: (config: RouteCalculatorConfig) => Promise<void>;
}Vanilla Types
// RouteMap
interface RouteMapConfig extends MapConfig {
onError?: (error: Error) => void;
}
class RouteMap {
constructor(config: RouteMapConfig);
initialize(element: HTMLElement): Promise<void>;
destroy(): void;
isReady(): boolean;
getMap(): google.maps.Map | null;
getCurrentRoute(): Route | null;
renderRoute(route: Route): void;
clearRoute(): void;
setCenter(location: LatLng): void;
getCenter(): LatLng | null;
setZoom(zoom: number): void;
getZoom(): number | null;
fitBounds(bounds: MapBounds): void;
getBounds(): MapBounds | null;
addMarker(location: LatLng, options?: MarkerOptions): void;
removeMarker(id: string): void;
clearMarkers(): void;
}
// RouteOptimizer
interface RouteOptimizerEvents {
'status-change': OptimizationStatus;
progress: { progress: number; step: string };
success: OptimizationResponse;
error: Error;
start: void;
reset: void;
}
class RouteOptimizer {
constructor(config: RouteCalculatorConfig);
get status(): OptimizationStatus;
get data(): OptimizationResponse | null;
get error(): Error | null;
get isLoading(): boolean;
get isSuccess(): boolean;
get isError(): boolean;
initialize(): Promise<void>;
optimize(request: OptimizationRequest): Promise<OptimizationResponse>;
updateProgress(progress: number, step?: string): void;
reset(): void;
reinitialize(config: RouteCalculatorConfig): Promise<void>;
destroy(): void;
on<K extends keyof RouteOptimizerEvents>(
event: K,
listener: (data: RouteOptimizerEvents[K]) => void
): void;
off<K extends keyof RouteOptimizerEvents>(
event: K,
listener: (data: RouteOptimizerEvents[K]) => void
): void;
}Type Guards
Utility functions for type checking:
// Check if location is valid
function isValidLatLng(location: any): location is LatLng {
return (
typeof location === 'object' &&
typeof location.lat === 'number' &&
typeof location.lng === 'number' &&
location.lat >= -90 &&
location.lat <= 90 &&
location.lng >= -180 &&
location.lng <= 180
);
}
// Check if stop is valid
function isValidStop(stop: any): stop is Stop {
return typeof stop === 'object' && typeof stop.id === 'string' && isValidLatLng(stop.location);
}
// Check if route is valid
function isValidRoute(route: any): route is Route {
return (
typeof route === 'object' &&
Array.isArray(route.stops) &&
route.stops.length >= 2 &&
route.stops.every(isValidStop)
);
}Usage:
function processRoute(data: unknown) {
if (isValidRoute(data)) {
// TypeScript knows data is Route
routeMap.renderRoute(data);
} else {
console.error('Invalid route data');
}
}Generic Types
For advanced type safety:
// Generic Stop with custom metadata
interface Stop<T = Record<string, any>> {
id: string;
location: LatLng;
name?: string;
address?: string;
duration?: number;
metadata?: T;
}
// Usage
interface DeliveryMetadata {
orderId: string;
customerId: string;
packageWeight: number;
priority: 'low' | 'medium' | 'high';
}
const deliveryStop: Stop<DeliveryMetadata> = {
id: 'delivery-001',
location: { lat: 13.7563, lng: 100.5018 },
metadata: {
orderId: 'ORD-12345',
customerId: 'CUST-001',
packageWeight: 5.5,
priority: 'high',
},
};Utility Types
// Partial route for updates
type PartialRoute = Partial<Route> & {
stops: Stop[];
};
// Read-only route
type ReadonlyRoute = Readonly<Route> & {
readonly stops: readonly Readonly<Stop>[];
};
// Pick specific stop properties
type StopLocation = Pick<Stop, 'id' | 'location'>;
// Omit metadata
type BasicStop = Omit<Stop, 'metadata'>;
// Required properties
type RequiredStop = Required<Stop>;Type Imports
Import types from packages:
// From Core
import type {
LatLng,
Stop,
Route,
RouteOptions,
MapConfig,
MapBounds,
OptimizationRequest,
OptimizationResponse,
} from '@route-optimization/core';
// From React
import type {
UseRouteMapOptions,
UseRouteMapReturn,
UseMapControlsReturn,
UseRouteOptimizationResult,
} from '@route-optimization/react';
// From Vue
import type {
UseRouteMapOptions,
UseRouteMapReturn,
UseMapControlsReturn,
UseRouteOptimizationResult,
} from '@route-optimization/vue';
// From Vanilla
import type {
RouteMapConfig,
OptimizationStatus,
RouteOptimizerEvents,
} from '@route-optimization/vanilla';Best Practices
1. Use Strict Types
Enable strict TypeScript options:
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"strictNullChecks": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}2. Type Assertions
Use type guards instead of assertions:
// ✅ Good - Type guard
if (isValidRoute(data)) {
processRoute(data);
}
// ❌ Avoid - Type assertion
processRoute(data as Route);3. Const Assertions
Use const assertions for literal types:
const mapConfig = {
apiKey: 'YOUR_API_KEY',
mapTypeId: 'roadmap',
zoom: 12,
} as const;4. Generic Constraints
Constrain generic types appropriately:
function getStopMetadata<T extends Record<string, any>>(
stop: Stop<T>,
key: keyof T
): T[keyof T] | undefined {
return stop.metadata?.[key];
}Next Steps
- Explore Customization options
- Learn about Performance optimization
- Check out API Reference