mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmUtilsupdated 08 Aug 2026

string-natural-compare

string-natural-compare is a CommonJS comparator for JavaScript Array.sort. It orders digit runs by their numeric value, so img2 comes before img10, without converting huge numbers to JavaScript Number. It can fold case and apply a caller-supplied character alphabet, and it throws when either compared value is not a string. It is a fast deterministic alphanumeric sorter, not a locale-aware collator, semantic version comparator, filesystem walker, or object sorting library.

Verdict

Still a capable tiny comparator for machine-oriented strings and arbitrarily long digit runs. New user-facing applications should start with `Intl.Collator({numeric: true})`; install this only when its deterministic ASCII-like order or explicit alphabet is the actual requirement.

API stability5/5The entire public contract is one comparator with two optional settings, and version 3.0.1 has remained unchanged since January 2020. The implementation is dependency-free and the README examples line up with source behavior. That stability is strong for existing CommonJS users, though there is no formal ESM export or bundled declaration to stabilize modern consumption patterns.
Docs4/5The README explains natural versus standard order, every argument and option, large integer handling, object sorting, precomputed keys, a Russian custom alphabet, case-insensitive ties, and the warning against digits in alphabets. It does not explain UTF-16 versus locale collation, TypeScript and ESM interop, mutation by Array.sort, null normalization, or the permanent alphabet-map cache visible in source.
Maintenance2/5The current 3.0.1 release was published January 21, 2020. The default branch received CI and documentation maintenance in 2023 and GitHub reports a repository push in March 2024, so it is not wholly abandoned, but there has been no package release in more than six years. One open issue or pull request is a small queue, yet modern packaging and types remain unaddressed.
Ecosystem3/5The package recorded 4,671,756 downloads in the measured week, has no runtime dependencies, and can drop into any Array.sort call. The repository has 51 stars and no integrations or plugin system. Its biggest ecosystem competitor is built into JavaScript itself: Intl.Collator provides numeric, language-aware sorting without adding a package on supported runtimes.

Use it if

  • You sort filenames, room numbers, build labels, or other ASCII-heavy identifiers containing digit runs
  • Your strings may contain integers larger than Number.MAX_SAFE_INTEGER and must still sort by magnitude
  • You need a custom explicit character order that is stable across machines
  • A small dependency-free CommonJS comparator fits your existing runtime and build
Skip it if

Setup reality

npm install string-natural-compare adds no dependencies, peers, native build, credentials, or configuration. Version 3.0.1 exports one CommonJS function, so require('string-natural-compare') is the native form. ESM consumers depend on Node or bundler CommonJS interop and should default-import only after testing their target. No TypeScript declarations are included; add a small local declaration or use a separately maintained type package if your dependency policy permits one. Pass the function directly to Array.sort for case-sensitive strings. For case-insensitive comparison, wrap it and pass {caseInsensitive: true}; equal folded strings return 0, so their relative order relies on modern JavaScript's stable sort. Both inputs must already be strings. Decide explicitly where nulls go and which property to compare before invoking it. The algorithm recognizes ASCII digits 0 through 9, ignores numeric overflow by comparing digit-run lengths and characters, and uses UTF-16 code-unit ordering for other characters. That is deterministic but not linguistic. A custom alphabet rebuild is cached by its full string, which helps repeated fixed options but can retain memory if alphabets come from unbounded user input. Do not include digits in that alphabet because the README calls the behavior undefined. Array.sort mutates its array, and comparators run many times, so precompute lowercase or composite keys for large object lists as the README recommends rather than repeatedly transforming inside the callback.

Patterns

Sort filenames in natural ordersort-filenames

const naturalCompare = require('string-natural-compare');

const files = ['img10.png', 'img2.png', 'img1.png'];
files.sort(naturalCompare);
// ['img1.png', 'img2.png', 'img10.png']

Array.sort mutates files. Use files.toSorted(naturalCompare) or [...files].sort(...) when the original order must survive.

Return a naturally sorted copysort-without-mutation

const sortedFiles = files.toSorted(naturalCompare);

toSorted is available in modern JavaScript runtimes. Use a spread copy before sort when supporting older engines.

Ignore case during comparisonsort-case-insensitive

const options = { caseInsensitive: true };
const compareInsensitive = (a, b) => naturalCompare(a, b, options);
const labels = ['B2', 'a10', 'A2'].sort(compareInsensitive);

Strings equal after lowercasing compare as 0, so their input order is preserved by stable modern Array.sort.

Sort records by one natural keysort-objects-by-property

rooms.sort((a, b) => naturalCompare(a.room, b.room));

Both properties must be strings. Normalize missing values before calling the comparator or it throws TypeError.

Sort by street, then roomsort-multiple-fields

rooms.sort((a, b) =>
  naturalCompare(a.street, b.street, { caseInsensitive: true }) ||
  naturalCompare(a.room, b.room)
);

Comparator zero falls through to the next field. Keep each field's case and locale policy explicit.

Precompute keys for a large object listprecompute-sort-keys

const keyed = cars.map((car) => ({
  value: car,
  key: `${car.make} ${car.model}`.toLowerCase(),
}));
keyed.sort((a, b) => naturalCompare(a.key, b.key));
const sortedCars = keyed.map(({ value }) => value);

The README recommends precomputation when transformation would otherwise repeat during many comparator calls.

Compare integer strings beyond Number precisionsort-large-integers

const ids = [
  '265812277985321589735871687040841',
  '1165874568735487968325787328996865',
];
ids.sort(naturalCompare);

The algorithm compares digit-run lengths and digits rather than converting to Number, so it avoids precision loss.

Reverse natural ordersort-descending

versions.sort((a, b) => naturalCompare(b, a));

This reverses the comparator but still does not implement semantic version rules for prereleases or build metadata.

Place missing values lasthandle-null-values

function compareNullable(a, b) {
  if (a == null) return b == null ? 0 : 1;
  if (b == null) return -1;
  return naturalCompare(String(a), String(b));
}
values.sort(compareNullable);

The package accepts strings only. Choose an explicit null policy instead of blindly converting null to the text 'null'.

Apply an explicit character alphabetuse-custom-alphabet

const russianAlphabet = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя';
const options = { alphabet: russianAlphabet };
letters.sort((a, b) => naturalCompare(a, b, options));

Do not put digits in the custom alphabet; the README says that causes undefined behavior. Reuse fixed alphabet strings so their cached maps remain bounded.

Add a local TypeScript declarationtype-commonjs-module

// types/string-natural-compare.d.ts
declare module 'string-natural-compare' {
  interface Options { caseInsensitive?: boolean; alphabet?: string }
  function naturalCompare(a: string, b: string, options?: Options): number;
  export = naturalCompare;
}

Version 3.0.1 does not publish declarations. Keep the shim aligned with the README's two options.

Use locale-aware numeric sorting insteaduse-native-collator

const collator = new Intl.Collator(undefined, {
  numeric: true,
  sensitivity: 'base',
});
const sorted = labels.toSorted(collator.compare);

Intl.Collator is usually the better user-facing choice because it understands locale collation; results can differ by locale and runtime data.

Alternatives

PackageRegistryPick it when
natural-compare-litenpmYou want another tiny natural comparator with a long-established browser-oriented implementation
natural-orderbynpmYou need iteratee-based ordering of objects, multiple fields, and ascending or descending directions
natsortnpmYou want configurable natural sorting with additional date, hexadecimal, and insensitive modes
javascript-natural-sortnpmYou maintain an older project already built around its comparator and case-insensitive flag