When managing configuration via package.json/tsconfig.json, treat version and target specifiers as compatibility controls—not defaults. Choose constraints based on the dependency/toolchain’s real compatibility behavior, and wire compatibility between packages explicitly.
Apply these rules:
^; use ~x.y.z or a fixed version (and document the exception).@types/*) are fixed/unchangeable and don’t assume compatible upgrades.^ only when the dependency truly follows semver and you’re OK with patch/minor updates.~ when you only want patch updates.tsconfig module/target settings match current TypeScript semantics (e.g., prefer Node16/Node18 settings over ambiguous NodeNext if TS changed behavior).Example:
{
"dependencies": {
"langium": "1.2.0", // non-semver: pin
"chokidar": "^3.6.0", // semver: allow compatible updates
"@iconify/utils": "3.0.1" // pinned to known-good version
},
"peerDependencies": {
"mermaid": "~11.7.0" // compatible minor/patch range
}
}
And for tsconfig.json, keep module/moduleResolution consistent with the TS version you run (e.g., Node16/Node16 or Node18/Node16), rather than blindly using NodeNext.
Enter the URL of a public GitHub repository