Intl.ListFormat при пустом массивеНаиболее показательным местом, где пустые массивы напрямую влияют на
результат, является форматирование списков через
Intl.ListFormat.
Метод format не вызывает ошибок при передаче пустого
массива:
const formatter = new Intl.ListFormat('ru', {
style: 'long',
type: 'conjunction'
});
formatter.format([]); // ""
Результат — пустая строка. Это не исключение и не null,
а именно строковое значение нулевой длины.
Такое поведение важно учитывать, поскольку логика визуализации списка может неожиданно «исчезнуть», если данные не были проверены.
Intl.ListFormat ориентирован на естественный язык.
Пустой список не имеет лингвистического представления. В языковых
моделях:
Поэтому вместо специального маркера или выбрасывания ошибки используется нейтральное поведение.
Проблема проявляется в цепочках рендеринга:
const formatter = new Intl.ListFormat('en');
const tags = [];
const result = formatter.format(tags);
console.log(`Tags: ${result}`);
Результат:
Tags:
Семантически это может быть некорректно, поскольку двоеточие остаётся, а содержимое исчезает.
Часто требуется явная обработка до вызова
Intl.ListFormat:
function formatList(list, formatter) {
if (!list || list.length === 0) {
return '—';
}
return formatter.format(list);
}
Такой подход отделяет логику интернационализации от бизнес-правил отображения.
formatToParts и
пустые массивыМетод formatToParts возвращает структурированное
представление списка:
const formatter = new Intl.ListFormat('ru');
formatter.formatToParts([]); // []
Результат — пустой массив частей.
Это поведение критично для UI-рендеринга, где ожидается массив сегментов. Отсутствие элементов означает отсутствие структуры, а не ошибку.
В приложениях, где данные приходят асинхронно, пустые массивы часто являются промежуточным состоянием:
Использование Intl.ListFormat без проверки приводит к
невозможности различить:
Intl.NumberFormatПустые массивы здесь не применяются напрямую, но косвенно встречаются
при map:
const nf = new Intl.NumberFormat('ru');
[].map(nf.format); // []
Проблема не в Intl, а в том, что форматирование не выполняется.
Intl.CollatorСортировка пустого массива безопасна:
const collator = new Intl.Collator('ru');
collator.compare; // функция
[].sort(collator.compare); // []
Пустой массив остаётся пустым, что ожидаемо для операций без элементов.
const list = [];
const output = list.length
? formatter.format(list)
: 'Нет элементов';
function safeFormatList(list, formatter, fallback = '—') {
return list?.length ? formatter.format(list) : fallback;
}
nullish логики данныхconst list = data?.tags ?? [];
const output = list.length === 0
? '—'
: formatter.format(list);
В некоторых локалях форматирование может возвращать строки с пробелами или символами-разделителями, но при пустом массиве поведение стабильно:
Это упрощает предсказуемость API независимо от языка.
При мемоизации форматирования списков пустой массив требует отдельного ключа:
const cache = new Map();
function cachedFormat(list, formatter) {
const key = list.length ? list.join('|') : '__empty__';
if (cache.has(key)) return cache.get(key);
const result = list.length ? formatter.format(list) : '';
cache.set(key, result);
return result;
}
Без специального ключа возможны конфликты между:
В функциональных цепочках:
const formatter = new Intl.ListFormat('ru');
const result = data
.filter(Boolean)
.map(x => x.label)
.filter(Boolean)
.let?.(list => formatter.format(list));
При отсутствии элементов результат становится пустой строкой, что может ломать последующие операции строковой агрегации.
Пустая строка после format([]) часто приводит к:
Поэтому проверка длины массива остаётся обязательной частью интеграции с Intl API.
undefined и nullХотя формально методы Intl ожидают массив строк, на практике:
formatter.format(undefined); // TypeError
formatter.format(null); // TypeError
Пустой массив отличается тем, что не вызывает ошибки, а возвращает допустимое значение. Это создаёт важное различие:
undefined → ошибкаnull → ошибка[] → валидный, но «пустой» результатДля Intl.ListFormat и связанных сценариев можно выделить
устойчивую модель:
Такое поведение делает API предсказуемым на уровне спецификации, но требует дополнительной логики на уровне приложения для различения состояний данных.