Найти тему

Пример улучшения функции сортировки в JavaScript / TypeScript

Сортировка — довольно распространённый вид операции с данными в JavaScript / TypeScript. Например, в одном из рабочих проектов .sort встречается 97 раз в 65 файлах. При этом важно, чтобы этот код был максимально читаемым и компактным.

Обратите внимание, что некоторые примеры, для упрощения восприятия, будут без типизации. В конце будет ссылка на рабочий TypeScript код целиком.

Рассмотрим следующий пример:

const MAP_TYPE_TO_ORDER: Record<FeatureType, number> = {
[FeatureType.Default]: 0,
[FeatureType.Local]: 1,
[FeatureType.Unknown]: 2,
};

function sortFeaturesByTypeAndTitle(features: Feature[]): Feature[] {
return [...features].sort((a, b) => {
const numA = MAP_TYPE_TO_ORDER[a.type];
const numB = MAP_TYPE_TO_ORDER[b.type];
if (numA !== numB) {
return numA - numB;
}
return a.title.localeCompare(b.title);
});
}

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

Для сортировки по алфавиту:

function inAbcOrderBy(prop) {
return (a, b) => a[prop].localeCompare(b[prop]);
}

Для сортировки по полю с перечислением (в нашем примере это type) в заданном порядке в виде массива (почему именно массив, объясню в конце):

function inCustomOrderBy(prop, order) {
return (a, b) => order.indexOf(a[prop]) - order.indexOf(b[prop]);
}

Для объединения нескольких функций сортировки в один метод .sort() напишем ещё одну вспомогательную функцию:

function inPriority(...sorters) {
return (a, b) => {
for (let i = 0; i < sorters.length; i++) {
const result = sorters[i](a, b);
if (result !== 0) return result;
}
return 0;
};
}

Осталось переписать наш пример используя эти функции:

const TYPE_ORDER = [
FeatureType.Default,
FeatureType.Local,
FeatureType.Unknown,
];

function sortFeaturesByTypeAndTitle(features: Feature[]): Feature[] {
return [...features].sort(
inPriority(
inCustomOrderBy('type', TYPE_ORDER),
inAbcOrderBy('title')
)
);
}

В итоге мы получили:

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

Более удобную, с точки зрения поддержки, настройку сортировки по типу, т.к. в случае изменения списка FeatureType не нужно будет обновлять индексы.

Код полностью.

Больше информации в Telegram канале https://t.me/around_dev