Caret o tilde: cosa consentono davvero ^1.2.3 e ~1.2.3 (2026)

  • VersionDude
  • guides
  • 7 min di lettura

Il versionamento semantico spiega cosa significa un numero di versione. La sintassi degli intervalli decide quali versioni accettate senza che vi venga chiesto. Non sono la stessa cosa, e il caret cambia le proprie regole sotto la 1.0.0.

Il versionamento semantico ti dice che cosa significa un numero di rilascio. Non ti dice quali rilasci il tuo progetto accetterà la prossima volta che qualcuno lancia un'installazione. Quello lo decide l'intervallo che hai scritto, ed è nella sintassi degli intervalli che si annidano quasi tutte le sorprese.

Due caratteri fanno quasi tutto il lavoro: la tilde `~` e il caret `^`.

La tilde permette modifiche di livello patch. Nella notazione della documentazione semver stessa, `~1.2.3` significa `>=1.2.3 <1.3.0-0`. Accetti 1.2.4 e 1.2.9, non accetti 1.3.0. Scritta con meno parti si allarga: `~1.2` equivale a `1.2.x`, e `~1` a `>=1.0.0 <2.0.0-0`.

Il caret permette tutto ciò che non modifica il numero diverso da zero più a sinistra. Per un rilascio normale significa che `^1.2.3` vale `>=1.2.3 <2.0.0-0`: tutti gli aggiornamenti minori e di patch fino alla major successiva. È l'impostazione predefinita di npm all'installazione, ed è per questo che quasi tutti i file di dipendenze sono pieni di caret.

Fin qui i due sembrano una semplice scelta tra prudente e permissivo. Poi si scende sotto la versione 1.0.0, e il caret cambia in silenzio la propria regola.

`^0.2.3` significa `>=0.2.3 <0.3.0-0`. Non `<1.0.0`. Poiché l'elemento diverso da zero più a sinistra è ora il minore, il caret tratta un incremento di minore come il cambiamento che rompe: su un pacchetto 0.x, un caret si comporta come una tilde.

`^0.0.3` significa `>=0.0.3 <0.0.4-0`. Cioè nessun aggiornamento. Con i primi due numeri a zero, la patch diventa l'elemento diverso da zero più a sinistra, e il caret ti inchioda a un solo rilascio.

Non è una stranezza da aggirare, è deliberato. Semver dice che un pacchetto 0.x non promette alcuna stabilità, quindi gli strumenti si rifiutano di presumere una compatibilità mai concessa. La conseguenza pratica è quella che conta: lo stesso caret ti dà tre livelli di libertà diversi a seconda di come è numerato il pacchetto, e un file di dipendenze pieno di caret non è uniformemente permissivo.

La seconda cosa da sapere è che un intervallo è un permesso, non una decisione. Ciò che viene davvero installato è registrato nel file di lock, e l'intervallo definisce soltanto dove un aggiornamento può spostarsi. Una squadra che legge l'intervallo e dimentica il lockfile finisce per cercare bug su due macchine con due versioni diverse che soddisfano entrambe la stessa riga.

Per scegliere, la regola onesta è breve. Il caret per le librerie di cui ti fidi che rispettino semver e che vuoi tenere aggiornate. La tilde quando un incremento di minore ti è già costato caro. Il blocco esatto quando davvero non puoi assorbire una sorpresa, accettando che gli aggiornamenti diventino un tuo compito. E verifica a che cosa si espande un intervallo prima di fidartene, perché `^0.x` non significa ciò che lo stesso simbolo significa una major più avanti.

Per vedere in cosa si traduce un intervallo prima di fare commit, incollalo nel verificatore di intervalli semver npm: carica l'elenco reale delle versioni di qualsiasi pacchetto dal registro npm e mostra quali versioni l'intervallo accetta, la più alta che installerebbe e quali pre-release scarta.

Progetto correlato