tsconfig and tooling

The compiler options that matter, why a fast bundler proves nothing about correctness, and how to wire checking into a build.

A tsconfig worth starting from

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "declaration": true,
    "sourceMap": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "dist"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
  • strict turns on the family of checks that find real bugs - keep it on.
  • noUncheckedIndexedAccess makes array[0] include undefined, which is honest about what an index lookup can return.
  • skipLibCheck skips type-checking your dependencies' declaration files and saves real build time.
  • target decides how modern the emitted JavaScript is, and module must match your runtime.
  • include limits the program to your source so generated folders stay out of it.

Where the types actually get checked

# check only - writes no files
npx tsc --noEmit

# build, including .d.ts declaration files
npx tsc

# a bundler strips types without checking them
npx esbuild src/index.ts --bundle --outfile=dist/bundle.js

# so run the checker separately, in CI and in a pre-commit hook
npx tsc --noEmit && npm test

Modern bundlers and runners such as esbuild, SWC, Vite and transpile-only ts-node strip types without verifying them. That is fast, and it means a green build proves nothing about type correctness unless tsc --noEmit runs somewhere.

TaskCommandNotes
Type check onlytsc --noEmitThe check CI must run
Emit JavaScripttscNeeded for a library that ships declaration files
Fast buildesbuild or swcStrips types and skips checking
Watch a projecttsc --watchIncremental feedback while editing
Reject implicit anytsc --noImplicitAnyAlready included in strict
⚠️
If the pipeline only transpiles, a type error can still reach production. Add tsc --noEmit as its own CI step - checking types is the entire reason you chose TypeScript.

FAQ

Why is tsc slow on a large project?
Checking scales with program size. Use project references and --incremental, keep include narrow, and leave type checking out of the hot reload path.
Do I need a separate build step for Node?
Only for publication or older runtimes. Recent Node can execute TypeScript directly for scripts, but shipping compiled JavaScript with declarations is still the safe choice for libraries.

Basic types and inference Interfaces, type aliases and generics

Last refreshed 2026-09-18.