Skip to main content

How to Manage Different TypeScript Versions

You push a change, CI fails. Your colleague runs tsc locally and it compiles fine. You run it and get three new errors. Sound familiar? Nine times out of ten, this is a TypeScript version mismatch. Different machines, different projects, or a recent upgrade you didn't quite plan for can all cause this kind of friction.

This guide walks through how to check, install, and manage TypeScript versions across projects, how to upgrade safely, and what to expect from the latest releases.

Checking Your TypeScript Version

To see which version your project is using, run:

tsc --version

Keep in mind this shows the version of tsc that's on your PATH, which may be a global install rather than your project's local one. To check the version your project actually uses, look in node_modules/.bin/tsc:

./node_modules/.bin/tsc --version

You can also check your package.json under devDependencies:

"devDependencies": {
"typescript": "^5.8.0"
}

If you're using Convex, it's worth confirming your TypeScript version against what the platform requires before you start building.

Updating TypeScript

To install the latest stable release:

npm install typescript@latest

If you need a specific version:

npm install typescript@5.8.3

For Convex projects, staying current pays off. Convex's end-to-end type safety relies on accurate type inference across client and server, and older TypeScript versions can miss things the newer compiler catches.

Installing a Specific TypeScript Version

When a project requires a particular version, install it as a dev dependency:

npm install typescript@5.4.5 --save-dev

You can also use npx to run a specific version without touching your project's installation:

npx typescript@5.4.5 tsc --version

This is handy when you want to test whether a version works before committing to the upgrade. Libraries like convex-helpers may require specific TypeScript versions to use their advanced typing features.

Before You Upgrade: Testing a New Version

Blindly running npm install typescript@latest in a production project is how you end up with a broken build on Friday afternoon. Here's a safer approach:

Step 1: Install the new version in a branch

npm install typescript@6.0.0 --save-dev

Step 2: Run a type check without emitting output

npx tsc --noEmit

This catches all type errors the new version would surface without touching your compiled files. Fix any issues before merging.

Step 3: Check the release notes

TypeScript's release notes document every breaking change. The team flags anything that could cause a compile error during an upgrade. Skimming the "Breaking Changes" section takes five minutes and can save you hours.

Step 4: Update @types packages

After upgrading TypeScript, update your type definitions too:

npm update @types/node @types/react

Version mismatches between TypeScript and @types packages are a common source of confusing errors.

Handling Multiple TypeScript Versions Across Projects

The core problem with multiple projects is that a global TypeScript install creates a shared dependency nobody agreed to. When you or a teammate runs tsc, it uses whichever version is on your PATH rather than what the project actually needs. That's where version drift creeps in.

The fix is to treat TypeScript like any other dependency: install it locally per project, pin it in package.json, and commit your lockfile. Each project then carries its own tsc in node_modules/.bin/, and there's no conflict between them.

# Project A pins TypeScript 5.4
npm install typescript@5.4.5 --save-dev

# Project B pins TypeScript 6.0
npm install typescript@6.0.0 --save-dev

Always invoke TypeScript through npm scripts or npx rather than the bare tsc command, so you're guaranteed to hit the local version:

"scripts": {
"typecheck": "tsc --noEmit",
"build": "tsc"
}

Using .nvmrc for Node alignment:

If your team uses nvm, a .nvmrc file in each project root keeps Node versions consistent alongside TypeScript:

22.0.0

Running nvm use in the directory switches Node automatically. TypeScript is still controlled by your local install, but consistent Node versions prevent subtle tooling differences across machines.

For the full npm-side workflow including how to handle version conflicts, npm overrides, and publishing packages with type definitions, see the TypeScript and npm guide.

If you're writing Convex functions, version consistency also matters for validation. The same code should type-check the same way on every machine, and a mismatched TypeScript version is a common reason it doesn't.

TypeScript Versions in VS Code

Here's something that catches a lot of developers off guard: VS Code ships with its own bundled version of TypeScript for IntelliSense and error highlighting. That version is independent of the one in your node_modules. So you can have TypeScript 6.0 installed in your project but VS Code is still using 5.3 internally, and they may disagree on certain errors.

To tell VS Code to use your project's TypeScript version instead:

  1. Open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P)
  2. Search for "TypeScript: Select TypeScript Version"
  3. Choose "Use Workspace Version"

You can also set this permanently in .vscode/settings.json:

{
"typescript.tsdk": "node_modules/typescript/lib"
}

Commit it to your repo so the whole team gets the same editor behavior automatically.

Targeting the Right ECMAScript Version

To target a specific ECMAScript version for output, use the --target flag:

tsc --target es2020

For TypeScript 6.0 and above, es5 is no longer a valid target. The minimum is es2015.

Use @types packages to match the typings with your runtime environment:

npm install @types/node@22

If you use complex filters in Convex, getting the right TypeScript target configured is what keeps them from failing at the type level.

Using Version-Specific Features

For features tied to certain TypeScript versions, you can configure the standard library with --lib:

tsc --lib es2022

This controls which built-in types TypeScript knows about, separate from the compilation target. For example, to use Array.prototype.at() without errors, you need lib: ["es2022"] even if your target is es2015.

Understanding which generics<T> and utility types are available in your version helps you write more effective code. Features like decorators and optional chaining landed in specific TypeScript releases, so it's worth checking before you start using them in a version-constrained project.

TypeScript 6.0 and the Road to 7.0

TypeScript 6.0 was released in March 2026 and is worth knowing about even if you're not upgrading immediately. It includes several breaking changes that affect existing projects:

Key breaking changes in TypeScript 6.0:

  • strict mode is now enabled by default
  • target: "es5" is deprecated; the minimum target is now es2015
  • moduleResolution: "classic" has been removed; use "bundler", "node16", or "nodenext"
  • esModuleInterop and allowSyntheticDefaultImports can no longer be set to false

If you're upgrading from TypeScript 5.x, the team's ts5to6 migration tool can update your tsconfig.json automatically:

npx ts5to6

The good news: 95% of TypeScript 5.x codebases compile without changes under TypeScript 6.0. The compiler also tells you exactly what to set rootDir to if it changed.

TypeScript 7.0 is the next major milestone, built on a rewritten compiler. If you want a full breakdown of what that means for the ecosystem, the TypeScript and GitHub guide covers the Go port project in detail, including how to track its progress and what to expect from the upgrade path.

Sorting Out Version Mismatches

When TypeScript errors appear after an upgrade or a change in environment, the problem is almost always coming from one of three places:

  1. Your project's package.json: check the typescript version under devDependencies
  2. Which tsc is actually running: the global install vs. your project's local one can silently differ
  3. VS Code's TypeScript version: it uses its own bundled version unless you've set "Use Workspace Version" (covered in the section above)

The @types packages are a fourth source of confusion. If you upgraded TypeScript but not your type definitions, the two can go out of sync and produce errors that look like compiler bugs.

Run this to quickly compare what's global vs. local:

./node_modules/.bin/tsc --version # what your project uses
tsc --version # what's on your PATH

If those two differ, you've found your problem. When working with Convex's API generation, version mismatches can cause unexpected type errors that are hard to trace without checking all three locations above.

For resolving version conflicts between packages (including npm overrides and npm ls typescript), the TypeScript and npm guide has the full troubleshooting workflow.

Closing Thoughts on TypeScript Versions

Version management is mostly a setup problem. Get it right once, per project, and you rarely have to think about it again. Install TypeScript locally, commit your lock file, set VS Code to use the workspace version, and run tsc --noEmit before any upgrade. That workflow handles 90% of the friction.

When you do upgrade, read the breaking changes section in the release notes. TypeScript's team is careful about this, and the notes are clear. A few minutes of reading beats debugging mysterious type errors after the fact.