Understanding Caret and Tilde in SemVer for JavaScript
Semantic Versioning (SemVer) governs how JavaScript package managers
like npm and Yarn handle dependency upgrades. When defining dependencies
in a package.json file, prefixing version numbers with a
caret (^) or a tilde (~) dictates whether the
project automatically accepts minor feature releases or restricts
updates exclusively to bug fixes. Understanding how these two operators
resolve versions prevents unexpected breaking changes while ensuring
projects receive critical security patches.
Semantic Versioning Structure
SemVer uses a three-part versioning system structured as
MAJOR.MINOR.PATCH (for example, 1.4.2):
- MAJOR: Contains breaking API changes.
- MINOR: Adds backward-compatible functionality.
- PATCH: Delivers backward-compatible bug fixes.
Package managers use version range prefixes to determine how far a
package can automatically upgrade when running npm update
or npm install.
The Tilde
(~) Operator: Patch Updates Only
The tilde operator provides conservative version matching by allowing patch-level updates while locking the major and minor versions. It is best suited for environments requiring high stability where even non-breaking feature additions might introduce regressions.
~1.2.3matches any version from>=1.2.3up to<1.3.0. It allows1.2.4and1.2.9, but excludes1.3.0.~1.2matches any version from>=1.2.0up to<1.3.0.~1matches any version from>=1.0.0up to<2.0.0.
The Caret
(^) Operator: Minor and Patch Updates
The caret operator is the default behavior in npm. It allows
backward-compatible updates by locking the leftmost non-zero digit in
the version string. For stable releases (>=1.0.0), the
caret allows both minor and patch releases, but blocks major breaking
updates.
^1.2.3matches any version from>=1.2.3up to<2.0.0. It allows1.3.0and1.9.1, but excludes2.0.0.^1.0.0allows any1.x.xrelease up to, but not including,2.0.0.
Caret Behavior with Pre-1.0.0 Versions
In SemVer, major version zero (0.y.z) indicates initial
development where the public API is unstable and any change could be
breaking. The caret adapts to this rule by locking the first non-zero
number:
^0.2.3matches>=0.2.3 <0.3.0(locks the minor version because it is the first non-zero digit).^0.0.3matches only0.0.3(locks the patch version because it is the first non-zero digit).
Quick Comparison
| Prefix | Definition in
package.json |
Resolves To Range |
|---|---|---|
Tilde
(~) |
~1.4.2 |
>=1.4.2 <1.5.0 |
Caret
(^) |
^1.4.2 |
>=1.4.2 <2.0.0 |
Tilde Zero
(~) |
~0.4.2 |
>=0.4.2 <0.5.0 |
Caret Zero
(^) |
^0.4.2 |
>=0.4.2 <0.5.0 |
| Exact Version | 1.4.2 |
Only 1.4.2 |
Summary
Use the caret (^) when you want your project to
automatically benefit from new features and bug fixes without breaking
existing code. Use the tilde (~) when you want to minimize
risk by only accepting patch-level bug fixes. For absolute control and
zero automatic version movement, omit both prefixes to lock the exact
version.