`tsconfig.json`

The Knobs That Shape Your Project

`tsconfig.json`

`tsconfig.json` is where you choose strictness, module format, target, JSX, paths, and dozens more. The most-load-bearing file in a TS project.

5 min read Level 2/5 #typescript#tsconfig#config
What you'll learn
  • Read a `tsconfig.json` and know what each section does
  • Pick a reasonable baseline for a new project
  • Know which options matter most

tsconfig.json controls everything about how TS compiles your code. The default tsc --init output is overwhelming — here are the options that actually matter.

A Sensible Modern Baseline

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "lib": ["ES2022", "DOM"],
    "jsx": "react-jsx",

    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    "esModuleInterop": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,

    "noEmit": true,
    "resolveJsonModule": true,
    "allowImportingTsExtensions": true
  },
  "include": ["src"]
}

The Options That Matter Most

strict: true

Turns on all strict family checks at once:

  • noImplicitAny
  • strictNullChecks
  • strictFunctionTypes
  • strictBindCallApply
  • strictPropertyInitialization
  • alwaysStrict
  • noImplicitThis
  • useUnknownInCatchVariables

Always turn this on for new code. It’s the entire point of TS.

target and lib

  • target — the JS version the compiler emits (e.g., ES2022).
  • lib — which built-in libraries’ types are available (DOM, ES2022, WebWorker…).

module and moduleResolution

  • module — output module format. Use ESNext if a bundler does final transpilation.
  • moduleResolution: "Bundler" — for projects shipped through Vite, esbuild, webpack, etc. Use "NodeNext" for pure Node libraries.

noEmit

Set when the bundler does the actual compilation. TS becomes “type checker only” — you don’t pollute dist/ with TS-emitted files.

noUncheckedIndexedAccess

Makes arr[0] produce T | undefined instead of T. Catches a huge class of bugs.

exactOptionalPropertyTypes

Makes { name?: string } and { name?: string | undefined } behave differently. Forces you to think about presence vs. explicit undefined.

isolatedModules

Each file must be safe to transpile alone. Required by Vite, esbuild, swc.

verbatimModuleSyntax

Forces explicit import type for type-only imports. Removes a bunch of edge cases around emission.

Include / Exclude

{
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Extends

For monorepos, extend a base config:

{
  "extends": "./tsconfig.base.json",
  "compilerOptions": { /* overrides */ }
}

Paths

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

Lets you write import { Button } from "@/components/Button". Note: TS only handles the type side — the bundler needs matching aliases.

Up Next

ES modules in a TS world — import, export, and the type-only variants.

Modules →