Типы ошибок RangeError, TypeError

В экосистеме Intl ошибка RangeError является одной из наиболее характерных, поскольку большинство функций интернационализации опираются на строго ограниченные наборы допустимых значений. Любое отклонение от стандартизированных параметров приводит к немедленному выбросу исключения.

Некорректные локали

Наиболее частый источник RangeError — передача недопустимой строки локали. Все конструкторы Intl используют механизм locale resolution, основанный на BCP 47.

new Intl.DateTimeFormat("xx-INVALID");

Подобная строка не соответствует спецификации языковых тегов, что приводит к:

  • RangeError: Invalid language tag: xx-INVALID

Аналогично ошибка возникает при некорректных расширениях:

new Intl.NumberFormat("en-US-u-invalid-extension");

Хотя механизм расширений допускает гибкость, неизвестные ключи или значения могут нарушать парсинг.

Недопустимые значения timeZone

Intl.DateTimeFormat строго проверяет IANA time zone database. Любое отклонение от списка допустимых зон приводит к RangeError.

new Intl.DateTimeFormat("en-US", {
  timeZone: "Moon/Crater"
});

Причина ошибки:

  • зона отсутствует в IANA tz database
  • строка не соответствует формату Area/Location

Ошибки в числовых и календарных параметрах

Множество опций Intl ограничены фиксированными наборами значений:

  • numberingSystem
  • calendar
  • collation
  • caseFirst
  • hourCycle

Пример:

new Intl.DateTimeFormat("en", {
  calendar: "unknown-calendar"
});

Результат:

  • RangeError: invalid calendar

Аналогично:

new Intl.NumberFormat("en", {
  numberingSystem: "latin-extreme"
});

Конфликтующие опции форматирования дат

Некоторые комбинации параметров также могут приводить к RangeError, когда спецификация исключает одновременное использование опций.

new Intl.DateTimeFormat("en", {
  dateStyle: "full",
  year: "numeric"
});

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


TypeError в Intl

TypeError в Intl возникает не из-за диапазона значений, а из-за нарушения типов данных, контекста вызова или структуры аргументов.

Некорректный контекст this

Методы прототипов Intl зависят от внутреннего состояния объекта. При отрыве метода от экземпляра нарушается связь с внутренними слотами.

const format = new Intl.NumberFormat("en").format;
format(1000);

Типичная ошибка:

  • TypeError: Illegal invocation

Причина:

  • потеря внутреннего [[NumberFormat]] контекста

Передача примитивов вместо объектов

Конструкторы Intl ожидают объект опций или undefined. Передача примитивов вызывает TypeError.

new Intl.DateTimeFormat("en", "invalid-options");

Результат:

  • TypeError: options must be an object

Допустимые формы:

  • undefined
  • объект {}

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

Методы вроде formatToParts, format, resolvedOptions требуют корректного экземпляра.

Intl.NumberFormat.prototype.format(100);

Здесь отсутствует привязка к экземпляру форматтера, поэтому внутренние данные отсутствуют, что приводит к:

  • TypeError: Intl.NumberFormat.prototype.format called on incompatible receiver

Ошибки при деструктуризации внутренних методов

Извлечение методов без привязки контекста приводит к аналогичным проблемам:

const { format } = new Intl.DateTimeFormat("en");
format(new Date());

Функция теряет ссылку на внутренние настройки локали и параметров форматирования.


Разграничение RangeError и TypeError в Intl

Поведение ошибок в Intl подчиняется строгой логике:

  • RangeError — значение корректного типа, но выходит за пределы допустимых значений спецификации
  • TypeError — нарушение структуры данных, контекста или типа аргументов

Сводная модель причин

RangeError возникает при:

  • невалидных локалях
  • неизвестных временных зонах
  • недопустимых календарях и системах нумерации
  • конфликтующих или запрещённых комбинациях опций

TypeError возникает при:

  • неверном типе параметров (примитив вместо объекта)
  • потере контекста this
  • вызове методов без экземпляра
  • использовании внутренних методов вне объекта Intl

Поведение движков и различия реализаций

Несмотря на стандартизацию ECMA-402, отдельные JavaScript-движки демонстрируют различия в деталях сообщений об ошибках:

  • V8 (Chrome, Node.js) формирует более строгие сообщения об Illegal invocation
  • SpiderMonkey (Firefox) чаще уточняет причину некорректной локали или опции
  • JavaScriptCore (Safari) иногда объединяет ошибки формата и диапазона в общий RangeError

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


Внутренние механизмы генерации ошибок

При создании экземпляра Intl выполняется несколько этапов:

  1. Парсинг локали
  2. Резолюция расширений Unicode
  3. Проверка доступности системных ресурсов (calendar, timeZone)
  4. Валидация опций форматирования
  5. Инициализация внутренних слотов объекта

На каждом этапе возможны различные категории отказов:

  • этап 1–3 → чаще RangeError
  • этап 4–5 → чаще TypeError

Типичные цепочки ошибок в реальных сценариях

function formatPrice(value, locale) {
  return new Intl.NumberFormat(locale, {
    style: "currency",
    currency: "US Dollar"
  }).format(value);
}

Ошибка возникает на этапе создания форматтера:

  • RangeError: invalid currency code

Корректный формат требует ISO 4217:

currency: "USD"

Другой пример:

const dtf = Intl.DateTimeFormat("en-US");
dtf.format.call({}, new Date());

Ошибка:

  • TypeError: format called on incompatible receiver

Причина — подмена контекста объекта.


Семантика устойчивости ошибок в Intl

Система Intl проектировалась как строго детерминированная. Это означает:

  • невозможность “мягкой деградации” при некорректных параметрах
  • немедленное прекращение выполнения при нарушении спецификации
  • отсутствие автоматической коррекции значений

Такой подход обеспечивает одинаковое поведение форматирования во всех окружениях, но увеличивает строгость проверки входных данных.


Поведение при цепочках вызовов

При вложенном использовании Intl ошибки не маскируются:

new Intl.DateTimeFormat(
  new Intl.NumberFormat("en").format(1000)
);

Если внутренний вызов возвращает некорректную строку локали, ошибка RangeError возникает на внешнем уровне, без попыток восстановления.


Особенности обработки валидации options

Объект options проходит глубокую нормализацию:

  • преобразование значений к строкам (где допустимо)
  • проверка принадлежности к enum-значениям
  • кросс-проверка зависимых параметров

Любое нарушение приводит либо к:

  • RangeError (если значение вне множества)
  • TypeError (если структура объекта нарушена)

Общая модель ошибок Intl

Поведение ошибок можно формализовать следующим образом:

  • допустимость типа → проверка TypeError
  • допустимость значения → проверка RangeError
  • допустимость комбинации → может приводить к любому из двух типов в зависимости от этапа проверки

Эта модель делает Intl одной из наиболее строго типизированных подсистем JavaScript, несмотря на отсутствие статической типизации в языке.