Проверка выражений

В Mapbox GL JS стили описываются декларативно, а динамическое поведение задаётся через выражения. Выражение представляет собой массив, где первый элемент — оператор, последующие — аргументы. Такой формат позволяет интерпретатору стиля выполнять вычисления без пользовательского кода во время рендеринга карты.

Базовый пример выражения:

["get", "population"]

Значение берётся из свойства объекта данных population.

Сложные выражения строятся вложенно:

["interpolate", ["linear"], ["zoom"], 5, 1, 10, 10]

Зависимость значения от масштаба карты задаётся через интерполяцию.

Контекст выполнения выражений

Выражения интерпретируются в рамках конкретного слоя и свойства стиля. Контекст определяет допустимые типы результата:

  • числовые выражения для line-width, opacity
  • цветовые выражения для fill-color, line-color
  • строковые выражения для text-field
  • булевы выражения для условий фильтрации

Несоответствие типа выражения ожидаемому контексту приводит к ошибкам валидации.

Типизация выражений и строгие ограничения

Система выражений Mapbox GL JS является строго типизированной. Каждый оператор имеет определённую сигнатуру.

Примеры:

  • ["+", number, number] → number
  • ["get", string] → any
  • ["==", value, value] → boolean
  • ["case", boolean, result, ...] → value

Нарушение сигнатуры приводит к ошибке при загрузке стиля или к игнорированию слоя.

Валидация через style specification

Основной уровень проверки выражений выполняется через спецификацию стилей Mapbox Style Specification. При загрузке стиля происходит синтаксический и семантический анализ.

Ключевые этапы:

  1. Проверка структуры JSON стиля
  2. Проверка допустимых свойств слоя
  3. Проверка типов значений
  4. Проверка выражений по схеме операторов

При обнаружении ошибки слой может быть полностью отключён или заменён значением по умолчанию.

Использование mapbox-gl-style-spec для проверки

Библиотека mapbox-gl-style-spec содержит валидатор стилей и выражений.

Пример программной проверки:

import validateStyle from "@mapbox/mapbox-gl-style-spec/lib/validate_style";

const style = {
  version: 8,
  sources: {},
  layers: [
    {
      id: "water",
      type: "fill",
      source: "map",
      paint: {
        "fill-color": ["get", "water_color"]
      }
    }
  ]
};

const errors = validateStyle(style);

console.log(errors);

Результат содержит список ошибок с указанием пути в стиле и причиной несоответствия.

Проверка выражений на уровне слоя

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

Типичный подход:

const expression = ["interpolate", ["linear"], ["zoom"], 0, 0, 10, 1];

При интеграции в слой валидатор проверяет:

  • корректность операторов
  • соответствие типов аргументов
  • допустимость использования функций в данном контексте

Ошибки времени выполнения

Даже при успешной валидации возможны ошибки во время рендеринга. Они фиксируются через событие карты:

map.on("error", (e) => {
  console.log(e.error);
});

Типичные runtime-проблемы:

  • отсутствие свойства в данных (["get", "missing"])
  • деление на ноль в выражениях
  • некорректный формат цвета
  • неожиданный тип значения из источника данных

Типичные ошибки выражений

Несоответствие типов

["+", "string", 10]

Ожидаются числа, строка делает выражение некорректным.

Ошибки вложенности

["get", ["get", "value"]]

Внутренний get возвращает динамический тип, что может нарушить ожидания внешнего оператора.

Неверный контекст цвета

["+", 1, 2]

Использование числового результата в свойстве, ожидающем цвет.

Ошибки фильтрации

["==", ["get", "type"], true]

Сравнение строки и булевого значения.

Проверка фильтров выражениями

Фильтры слоёв также являются выражениями:

filter: ["all",
  ["==", ["get", "type"], "park"],
  [">", ["get", "area"], 1000]
]

Проверка фильтра включает:

  • корректность логических операторов (all, any, none)
  • валидность сравнений
  • согласованность типов

Отладка выражений в сложных стилях

При работе с большими стилями выражения часто становятся вложенными и трудно читаемыми. Для анализа используется разбиение на подвыражения:

const zoomLevel = ["zoom"];

const width = [
  "interpolate",
  ["linear"],
  zoomLevel,
  5,
  1,
  10,
  20
];

Такой подход упрощает проверку и снижает вероятность ошибок типизации.

Проверка через инспекцию стиля

Получение текущего стиля позволяет анализировать выражения в рантайме:

const style = map.getStyle();

style.layers.forEach(layer => {
  console.log(layer.paint);
});

Хотя прямой встроенной валидации выражений на стороне API Mapbox GL JS нет, анализ JSON структуры стиля позволяет выявлять потенциальные проблемы до применения.

Сигналы и диагностика ошибок

Mapbox GL JS генерирует диагностические сообщения, которые содержат:

  • идентификатор слоя
  • путь к свойству
  • текст ошибки
  • тип выражения

Эти данные используются для локализации некорректного участка выражения в больших стилях.

Ограничения системы проверки выражений

Система валидации выражений имеет ряд ограничений:

  • отсутствие полноценного статического анализа пользовательских функций
  • невозможность предсказания всех runtime-значений данных
  • ограниченная проверка пользовательских GeoJSON свойств
  • зависимость от корректности входных данных источников

Из-за этого часть ошибок проявляется только при рендеринге, а не при загрузке стиля.

Согласованность данных и выражений

Корректность выражений зависит от структуры данных источников. Если выражение ожидает числовое поле, а источник содержит строку, результат становится непредсказуемым.

Типичный случай:

["get", "elevation"]

При числовой логике поля elevation строковое значение приведёт к некорректной интерпретации выражений интерполяции и сравнений.

Производственные подходы к проверке

В крупных проектах используется многоуровневая проверка:

  • статическая проверка JSON стиля
  • линтинг выражений перед деплоем
  • тестовые рендеры стилей
  • логирование ошибок Mapbox GL JS
  • контроль схемы GeoJSON данных

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