Back to TypeScript tutorials
Intermediate14 min read

tsconfig Strictness

Configure compiler strictness flags for maximum safety without blocking pragmatic migration paths.

The strict Flag and Its Family

`strict: true` enables `strictNullChecks`, `strictFunctionTypes`, `strictBindCallApply`, `strictPropertyInitialization`, `noImplicitAny`, `noImplicitThis`, and `alwaysStrict`. New projects should start with strict enabled from day one.

Migrating legacy JavaScript enables strict flags incrementally — turn on one flag per PR, fix violations, and prevent regression with CI. `strictNullChecks` alone catches the most production bugs.

  • `strict: true` enables the full suite
  • Enable flags incrementally in migrations
  • strictNullChecks has highest bug-finding ROI
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true
  }
}

High-Value Additional Flags

`noUncheckedIndexedAccess` adds `undefined` to indexed access — arrays and records require explicit checks. `exactOptionalPropertyTypes` distinguishes missing vs explicitly undefined optional props. `noImplicitReturns` ensures all code paths return in functions with return types.

`verbatimModuleSyntax` enforces explicit `import type` and prevents accidental value imports of types. Enable when tooling supports it for cleaner output and fewer circular import bugs.

  • noUncheckedIndexedAccess for array safety
  • exactOptionalPropertyTypes for precise optionals
  • verbatimModuleSyntax for clean imports

Module and Interop Settings

`esModuleInterop` and `allowSyntheticDefaultImports` simplify default imports from CommonJS modules. `isolatedModules` ensures each file transpiles independently — required for Babel and esbuild and catches re-export issues.

`skipLibCheck` skips typechecking of declaration files — faster builds with slightly less safety. Most projects enable it; fix upstream @types issues locally with module augmentation when needed.

  • isolatedModules for Babel/esbuild
  • esModuleInterop for CJS default imports
  • skipLibCheck for build speed

Project References and Monorepos

Split monorepos with `composite: true` and project references for incremental builds. Each package has its own tsconfig extending a base config with shared strict flags.

Path mapping at the root coordinates packages: `"references": [{ "path": "./packages/ui" }]`. `tsc --build` compiles the dependency graph in order, caching outputs.

  • Project references for monorepos
  • Shared base tsconfig for consistency
  • Incremental builds with composite

Balancing Strictness and Velocity

Stricter configs slow initial migration but accelerate long-term development. Document any intentional `@ts-expect-error` with ticket links and expiration plans — suppressions without context become permanent holes.

Use ESLint TypeScript rules (`@typescript-eslint`) alongside compiler flags for patterns the compiler cannot enforce — consistent type imports, explicit return types on exports, and ban on non-null assertions in critical paths.

  • Document ts-expect-error with tickets
  • ESLint complements compiler flags
  • Stricter configs pay off over time

Get In Touch


Ready to discuss your next project? Drop me a message.