Настройка TypeScript

TypeScript-проект с использованием MapLibre GL JS начинается с установки основной библиотеки и обеспечения корректной типизации API. Современные версии MapLibre GL JS распространяются с встроенными типами, однако в некоторых конфигурациях сборки может потребоваться явная настройка типов или подключение дополнительных объявлений.

npm install maplibre-gl

При использовании старых сборок или нестандартных окружений дополнительно подключается пакет типов:

npm install -D @types/maplibre-gl

В большинстве современных проектов достаточно одного пакета maplibre-gl, так как типы поставляются вместе с библиотекой.


Конфигурация TypeScript (tsconfig.json)

Корректная работа с MapLibre GL JS требует строгой настройки компилятора TypeScript. Основное внимание уделяется DOM-типации, модульной системе и строгому контролю null-значений.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "lib": ["DOM", "ES2020"],
    "types": []
  },
  "include": ["src"]
}

Ключевые моменты конфигурации:

  • DOM в lib обязателен для работы с HTMLElement и Map-контейнером
  • strict режим предотвращает ошибки при работе с GeoJSON и стилями
  • skipLibCheck снижает количество конфликтов в типах зависимостей
  • moduleResolution: Bundler предпочтителен при использовании Vite, Webpack 5 и аналогичных инструментов

Импорт MapLibre GL JS в TypeScript

Библиотека поддерживает ESM-импорт, что упрощает работу в современных сборщиках.

import maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";

Тип maplibregl.Map автоматически доступен после импорта.


Создание экземпляра карты с типизацией

Основная точка входа — класс Map. TypeScript позволяет строго типизировать параметры и события.

const map = new maplibregl.Map({
  container: "map",
  style: "https://demotiles.maplibre.org/style.json",
  center: [30.31413, 59.93863],
  zoom: 10
});

Типы параметров:

  • container: string | HTMLElement
  • style: StyleSpecification | string
  • center: [number, number]
  • zoom: number

Работа с типами координат и GeoJSON

MapLibre GL JS активно использует GeoJSON, поэтому TypeScript требует корректного описания географических данных.

import type { Feature, FeatureCollection, Point } from "geojson";

const point: Feature<Point> = {
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [30.31413, 59.93863]
  },
  properties: {
    name: "Center point"
  }
};

Использование строгих типов предотвращает ошибки в порядке координат и структуре объектов.


Добавление источников данных с типизацией

Источники данных в MapLibre GL JS строго типизированы через GeoJSONSourceSpecification.

map.on("load", () => {
  map.addSource("points", {
    type: "geojson",
    data: {
      type: "FeatureCollection",
      features: []
    }
  });
});

Для сложных проектов используется явное приведение типа:

import type { GeoJSONSourceSpecification } from "maplibre-gl";

const source: GeoJSONSourceSpecification = {
  type: "geojson",
  data: {
    type: "FeatureCollection",
    features: []
  }
};

map.addSource("points", source);

Добавление слоёв с контролем типов

Слои описываются через LayerSpecification. TypeScript позволяет строго контролировать структуру слоя.

map.addLayer({
  id: "points-layer",
  type: "circle",
  source: "points",
  paint: {
    "circle-radius": 6,
    "circle-color": "#ff0000"
  }
});

Типизация предотвращает ошибки в ключах paint и layout, которые чувствительны к названию и контексту слоя.


События карты и типизация обработчиков

MapLibre GL JS использует событийную модель, где TypeScript помогает безопасно работать с контекстом событий.

map.on("click", (e) => {
  console.log(e.lngLat.lng, e.lngLat.lat);
});

Для более строгой типизации событий:

map.on("click", (e: maplibregl.MapMouseEvent & maplibregl.EventData) => {
  const coordinates: [number, number] = [e.lngLat.lng, e.lngLat.lat];
});

Типизация событий особенно важна при работе с queryRenderedFeatures:

map.on("click", (e) => {
  const features = map.queryRenderedFeatures(e.point);
});

Использование Ref и жизненного цикла карты в TypeScript

В TypeScript-проектах часто требуется хранить ссылку на карту с учётом возможного null.

let map: maplibregl.Map | null = null;

function initMap(): void {
  map = new maplibregl.Map({
    container: "map",
    style: "https://demotiles.maplibre.org/style.json"
  });
}

Защита от null обязательна при дальнейших вызовах:

if (map) {
  map.setZoom(12);
}

Интеграция с Vite и Webpack

Vite

Vite автоматически поддерживает ESM и TypeScript, дополнительные настройки минимальны.

import maplibregl from "maplibre-gl";

CSS импортируется напрямую:

import "maplibre-gl/dist/maplibre-gl.css";

Webpack

При использовании Webpack требуется корректная обработка CSS и TypeScript:

module.exports = {
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: "ts-loader",
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  }
};

Расширение типов через declaration merging

TypeScript позволяет расширять типы MapLibre GL JS при добавлении пользовательских слоёв, контролов или свойств.

declare module "maplibre-gl" {
  interface Map {
    customMethod?: () => void;
  }
}

Это особенно полезно при создании архитектурных надстроек над картой.


Типизация пользовательских контролов

Контролы реализуются через интерфейс IControl.

class ZoomInfoControl implements maplibregl.IControl {
  private container!: HTMLElement;

  onAdd(map: maplibregl.Map): HTMLElement {
    this.container = document.createElement("div");
    this.container.className = "zoom-info";
    this.container.textContent = "Zoom control";
    return this.container;
  }

  onRemove(): void {
    this.container.remove();
  }
}

Добавление контролов:

map.addControl(new ZoomInfoControl());

Работа с style specification в TypeScript

Стиль карты описывается через StyleSpecification, что позволяет полностью контролировать структуру JSON-стиля.

import type { StyleSpecification } from "maplibre-gl";

const style: StyleSpecification = {
  version: 8,
  sources: {},
  layers: []
};

Такой подход снижает вероятность ошибок в сложных кастомных стилях.


Обработка ошибок типов при работе с API

TypeScript помогает выявлять несоответствия, однако некоторые ошибки возникают только во время выполнения. Для MapLibre GL JS характерны следующие защитные паттерны:

map.on("styledata", () => {
  const source = map.getSource("points");
  if (!source) return;
});

Явные проверки обязательны при работе с динамическими источниками и слоями.


Статическая типизация и производительность разработки

Использование TypeScript с MapLibre GL JS снижает количество runtime-ошибок при:

  • работе с GeoJSON структурами
  • управлении слоями и источниками
  • обработке событий карты
  • создании кастомных контролов
  • управлении стилями

Строгая типизация также упрощает масштабирование проекта, особенно при наличии множества слоёв и динамических данных.