The compiler and runtime
Type-check without emitting files
Use the compiler as a checker when another tool already transforms and bundles the source.
In most modern projects, tsc never produces the JavaScript you ship. Vite, esbuild, or another build tool strips the types and bundles the output, because doing that without type checking is dramatically faster. That leaves tsc with one job: checking.
Run the project checker without writing any output:
npx tsc --noEmit
The compiler checks the whole project but writes no JavaScript, no source maps, and no declaration files. Silence means success. Errors come out in the usual file, line, and message format, and the exit code is non-zero. That exit code is what scripts and CI care about.
Why the bundler is not enough
The two tools answer different questions. A bundler asks “can I transform and package this source?”. TypeScript asks “does this program respect its own type contracts?”.
A fast transpiler can produce JavaScript even when the types are wrong. This line bundles without complaint:
const port: number = 'three thousand'
Strip the annotation and it is valid JavaScript. Only the type checker reports the problem:
Type 'string' is not assignable to type 'number'.
So a green build proves very little about your types. Teams learn this the hard way when a refactor breaks twenty call sites and the deploy succeeds anyway.
Make checking a named command
Keep a separate type-check script in package.json:
{
"scripts": {
"typecheck": "tsc --noEmit"
}
}
Run npm run typecheck locally and in continuous integration. In CI, make it its own step next to the tests, so a type failure is reported as exactly that instead of hiding inside a build log.
You can also set "noEmit": true in tsconfig.json under compilerOptions instead of passing the flag. That keeps the script shorter and makes the intent explicit: this configuration exists for checking, another tool owns the output.
The habit that makes it pay off
Run the typecheck before you commit, not just before you deploy. The errors are cheapest when the code is still fresh in your head. I run it so often that I keep tsc --noEmit --watch open in a terminal tab while I work, and the editor’s red squiggles become a preview of what the command will say.
Try this: introduce a type error that is still valid JavaScript syntax, like the port line above. Confirm that your build tool transforms it happily while npm run typecheck rejects it.
Lesson completed