How to Choose and Pin a TypeScript Version for an Existing Project
Find your project's TypeScript compatibility boundaries, pin an exact npm version, and check the compiler, editor, build, and CI workflows.

The right TypeScript version for an existing project is not necessarily the newest one. Start with the compiler the project actually installs, find the versions its framework and tooling support, and test a candidate inside those boundaries. Then pin the version that passed—not just the version that happened to be on your machine.
Find the compiler the project uses now
Read package.json for the local typescript dependency and the scripts that build or check the project. Check package-lock.json for the resolved installation, and look at the version reported from the project directory:
npx tsc --version
Also identify any framework requirement and any tool that embeds TypeScript in its compiler or language service. Those tools may have a narrower compatibility window than code that merely calls tsc.
An editor can make this inventory confusing. VS Code’s TypeScript language service is separate from the installed compiler. If an editor suggestion disagrees with a local build, inspect which TypeScript version each is using before treating the difference as a code defect. In VS Code, open a TypeScript or JavaScript file, run TypeScript: Select TypeScript Version, and select the workspace version. You can also open the selector from the TypeScript version number in the status bar. Merely setting js/ts.tsdk.path does not activate the workspace version for IntelliSense; you still have to select it.
Establish the supported range first
A framework support table is a constraint, not a suggestion to try every major release. For example, Angular’s version table lists Angular 22.0.x with TypeScript >=6.0.0 <6.1.0. A project on that Angular line should select a candidate within that range and check its other tooling requirements as well.
Compiler-dependent integrations need their own check. The TypeScript 7.0 announcement says TypeScript 7 does not yet expose a stable programmatic API for tools that embed it. It advises projects using Vue, MDX, Astro, or Svelte to continue using TypeScript 6.0 for the time being. That is a different question from whether tsc alone can check your files. Do not infer editor or framework compatibility from a successful standalone compiler run.
Once you have those boundaries, choose a specific candidate release that fits all of them. There is no useful universal answer for an unspecified repository: its framework version, embedded tools, and existing configuration decide which candidates are worth testing.
Pin the candidate, not a moving target
In the following example, X.Y.Z is a placeholder for the full version number of a candidate you have checked against the project’s support ranges. Replace it before running the command:
npm install --save-dev --save-exact [email protected]
The resulting dependency entry should name that exact version rather than a range. For a project whose chosen candidate is X.Y.Z, the relevant part of package.json is:
{
"devDependencies": {
"typescript": "X.Y.Z"
}
}
Commit the updated package.json and package-lock.json together. The package entry records what you intended to select; the lockfile records the installation used when the project’s dependencies are installed. Check both after changing the compiler so another developer or CI does not silently work from an older lockfile. A local TypeScript installation also avoids relying on a compiler installed globally for unrelated projects.
Test the version in the workflows that matter
After a clean install from the committed project files, run npx tsc --version again in the project directory. It should report the candidate you pinned. Then run the build, tests, and CI checks that the repository already defines; use its actual scripts rather than substituting a new example command. Finally, confirm that VS Code’s version selector still shows the workspace version if you want IntelliSense to follow the project compiler.
Those results have a precise meaning. They show that this compiler and the participating tools work for the paths those checks exercise. They do not show that JavaScript will handle every runtime input correctly. If a check fails, compare the failing tool’s supported range, the resolved compiler version, and the reported error before deciding whether the cause is TypeScript itself, a declaration package, or another integration.
Treat the next version as an upgrade
Upgrade by changing the compiler dependency and lockfile together, reading the relevant release changes, and rerunning the same project checks. For example, TypeScript 5.9 changed DOM and typed-array declarations, which can surface errors involving Node.js Buffer. If that happens, inspect the affected types and the installed @types/node version; the error alone does not prove that application logic changed.
There is also a preparation step before adopting 7.0. TypeScript 6.0 deprecates options that 7.0 will not support. Setting "ignoreDeprecations": "6.0" can suppress those warnings while on 6.0, but it does not make the options work in 7.0. Address the settings and confirm that tools embedding the TypeScript API can support the intended version before making that jump.
