All questions

Semver Compare

Premium

Semver Compare

Semantic versioning gives every release a string like 1.4.2 or 2.0.0-rc.1 together with a precise rule for which release comes first. You are implementing that rule: semverCompare(a, b) parses two version strings and returns -1, 0, or 1 depending on which has the lower precedence. The format is MAJOR.MINOR.PATCH with an optional prerelease tag after a hyphen and optional build metadata after a plus sign. See the Semantic Versioning spec for the full precedence rules.

Signature

semverCompare(a: string, b: string): -1 | 0 | 1
// -1  a has lower precedence than b (a comes first)
//  0  a and b have equal precedence
//  1  a has higher precedence than b

Examples

semverCompare('1.2.3', '1.2.3');         // 0
semverCompare('1.0.10', '1.0.9');        // 1  (10 beats 9 numerically)
semverCompare('1.0.0-alpha', '1.0.0');   // -1 (a prerelease precedes the release)
semverCompare('1.0.0-beta.2', '1.0.0-beta.11');     // -1 (2 is below 11 as numbers)
semverCompare('1.0.0-alpha.1', '1.0.0-alpha.beta');  // -1 (a number ranks below a word)
semverCompare('1.0.0+build.9', '1.0.0');            // 0  (build metadata is ignored)

Notes

  • Three numeric fields — compare major, then minor, then patch as numbers, left to right; the first that differs decides the result.
  • Prerelease lowers precedence — a version with a prerelease tag comes before the same version without one, so 1.0.0-alpha precedes 1.0.0.
  • Identifier rules — split the prerelease on dots and compare left to right: numeric identifiers as numbers, a numeric identifier below a non-numeric one, otherwise by ASCII order; if one tag is a prefix of the other, the tag with more fields wins.
  • Build metadata is ignored — everything after the first + has no effect on ordering.
  • Well-formed input — you may assume both arguments are valid semver strings; you do not need to reject malformed input.
  • Return exactly -1, 0, or 1 — not a raw difference of two numbers.

FAQ

Why is build metadata ignored when comparing versions?
The semver spec defines build metadata (everything after the plus sign, like a commit hash or timestamp) as build-identifying information that carries no ordering meaning. So 1.0.0+build.1 and 1.0.0+build.2 have equal precedence, and you strip it off before comparing anything.
Why does a prerelease rank below the plain release?
A prerelease such as 1.0.0-alpha is an unfinished preview of 1.0.0, so it must come before the final release. Concretely, when the major.minor.patch triples are equal, a version that has a prerelease tag ranks below the same version without one.
How are prerelease identifiers like beta.2 and beta.11 ordered?
Split the prerelease on dots and compare identifiers left to right. Numeric identifiers compare as numbers (so 2 comes before 11, not after it), a numeric identifier always ranks below a non-numeric one, and two non-numeric identifiers compare by ASCII order. If every shared identifier ties, the tag with more fields wins.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium