---
# === IDENTITY ===
id: software/devops/typescript-tsconfig/2026
canonical_question: "TypeScript tsconfig patterns reference"
aliases:
  - "How to configure tsconfig.json for TypeScript projects"
  - "TypeScript compiler options best practices"
  - "tsconfig strict mode and moduleResolution setup"
  - "TypeScript project configuration cheat sheet"
entity_type: software_reference
domain: software > devops > TypeScript tsconfig Patterns
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === VERIFICATION ===
last_verified: 2026-02-28
confidence: 0.94
version: 1.0
first_published: 2026-02-28

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "TypeScript 5.5 (June 2024) — isolatedDeclarations, config extends array syntax"
  next_review: 2026-08-27
  change_sensitivity: medium

# === CONSTRAINTS ===
constraints:
  - "strict: true is non-negotiable for new projects — it enables strictNullChecks, noImplicitAny, and 7 other safety checks"
  - "moduleResolution must match your module setting — 'bundler' for Vite/webpack, 'nodenext' for pure Node.js"
  - "Never set skipLibCheck: false in large projects — it dramatically slows compilation by checking all node_modules .d.ts files"
  - "target and lib are separate concerns — target controls emit syntax, lib controls available type definitions"
  - "paths aliases require a corresponding setup in your bundler/runtime — TypeScript does NOT rewrite import paths at emit"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Using Deno (has built-in TypeScript with its own config)"
    use_instead: "Deno configuration docs at docs.deno.com/runtime/fundamentals/configuration/"
  - condition: "Using Bun (bunfig.toml handles most TS config)"
    use_instead: "Bun TypeScript docs at bun.sh/docs/typescript"

# === AGENT HINTS ===
inputs_needed:
  - key: "runtime"
    question: "Where does the compiled code run?"
    type: choice
    options: ["Browser (via bundler)", "Node.js", "Both (library)", "Cloudflare Workers"]
  - key: "bundler"
    question: "Which bundler do you use?"
    type: choice
    options: ["Vite", "webpack", "esbuild", "Rollup", "None (tsc only)", "Next.js"]
  - key: "project_type"
    question: "What type of project is this?"
    type: choice
    options: ["Application", "Library (published to npm)", "Monorepo package"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/devops/typescript-tsconfig/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-02-28)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/devops/eslint-prettier-config/2026"
      label: "ESLint + Prettier Configuration Reference"
    - id: "software/devops/vite-configuration/2026"
      label: "Vite Configuration Reference"
    - id: "software/devops/jest-configuration/2026"
      label: "Jest Testing Configuration Reference"
  solves: []
  alternative_to: []
  often_confused_with: []

# === SOURCES ===
sources:
  - id: src1
    title: "TSConfig Reference — TypeScript Official Docs"
    author: Microsoft
    url: https://www.typescriptlang.org/tsconfig/
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src2
    title: "The TSConfig Cheat Sheet — Total TypeScript"
    author: Matt Pocock
    url: https://www.totaltypescript.com/tsconfig-cheat-sheet
    type: technical_blog
    published: 2024-09-15
    reliability: high
  - id: src3
    title: "A guide to tsconfig.json — 2ality"
    author: Dr. Axel Rauschmayer
    url: https://2ality.com/2025/01/tsconfig-json.html
    type: technical_blog
    published: 2025-01-10
    reliability: high
  - id: src4
    title: "Modules — Choosing Compiler Options"
    author: Microsoft
    url: https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src5
    title: "What is a tsconfig.json"
    author: Microsoft
    url: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src6
    title: "TypeScript Compiler Options"
    author: Microsoft
    url: https://www.typescriptlang.org/docs/handbook/compiler-options.html
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src7
    title: "Configuring TypeScript — Total TypeScript Essentials"
    author: Matt Pocock
    url: https://www.totaltypescript.com/books/total-typescript-essentials/configuring-typescript
    type: technical_blog
    published: 2024-11-01
    reliability: high
---

# TypeScript tsconfig Patterns Reference

## TL;DR

- **Bottom line**: Start every project with `strict: true`, `moduleResolution: "bundler"` (or `"nodenext"` for pure Node), `target: "es2022"`, and `skipLibCheck: true` — then add only what your specific setup needs.
- **Key tool/command**: `tsc --showConfig` (shows the resolved config with all inherited/default values)
- **Watch out for**: Setting `paths` aliases without configuring the same aliases in your bundler — TypeScript resolves types but does NOT rewrite import paths in emitted JavaScript.
- **Works with**: TypeScript 5.0–5.7, Node.js 18+, all major bundlers (Vite, webpack, esbuild, Rollup).

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- `strict: true` is non-negotiable for new projects — it enables `strictNullChecks`, `noImplicitAny`, and 7 other safety checks
- `moduleResolution` must match your `module` setting — `"bundler"` for Vite/webpack, `"nodenext"` for pure Node.js
- Never set `skipLibCheck: false` in large projects — it dramatically slows compilation by checking all `node_modules` `.d.ts` files
- `target` and `lib` are separate concerns — `target` controls emit syntax, `lib` controls available type definitions
- `paths` aliases require a corresponding setup in your bundler/runtime — TypeScript does NOT rewrite import paths at emit

## Quick Reference

| Option | Recommended Value | Purpose |
|---|---|---|
| `strict` | `true` | Enables all strict type checks (non-negotiable) |
| `target` | `"es2022"` | Emit syntax level (top-level await, class fields) |
| `module` | `"esnext"` (bundler) / `"nodenext"` (Node) | Module system for output |
| `moduleResolution` | `"bundler"` / `"nodenext"` | How TS finds modules |
| `skipLibCheck` | `true` | Skip .d.ts checking (much faster builds) |
| `esModuleInterop` | `true` | Fixes CJS/ESM default import compatibility |
| `isolatedModules` | `true` | Required by esbuild/swc/Vite transpilers |
| `verbatimModuleSyntax` | `true` | Enforces explicit type-only imports (TS 5.4+) |
| `noUncheckedIndexedAccess` | `true` | Array/object index returns `T \| undefined` |
| `resolveJsonModule` | `true` | Allows importing `.json` files |
| `moduleDetection` | `"force"` | Treats every file as a module |
| `forceConsistentCasingInFileNames` | `true` | Prevents case-mismatch bugs on case-insensitive OS |
| `declaration` | `true` (libraries only) | Generates `.d.ts` files for consumers |
| `declarationMap` | `true` (libraries only) | Source maps for .d.ts (go-to-definition into source) |
| `incremental` | `true` | Caches compilation for faster rebuilds |
| `noEmit` | `true` (bundler projects) | Bundler handles emit; TS only type-checks |

## Decision Tree

```
START
├── Pure Node.js project (no bundler)?
│   ├── YES → module: "nodenext", moduleResolution: "nodenext"
│   └── NO ↓
├── Using Vite, webpack, esbuild, or Rollup?
│   ├── YES → module: "esnext", moduleResolution: "bundler", noEmit: true
│   └── NO ↓
├── Building a library for npm?
│   ├── YES → declaration: true, declarationMap: true, outDir: "./dist"
│   └── NO ↓
├── React project?
│   ├── YES → jsx: "react-jsx" (React 17+) or "react" (React 16)
│   └── NO ↓
├── Monorepo with project references?
│   ├── YES → composite: true, references: [...], incremental: true
│   └── NO ↓
└── DEFAULT → strict: true, target: "es2022", skipLibCheck: true
```

## Step-by-Step Guide

### 1. Initialize tsconfig.json

Generate a starter tsconfig with all options commented. [src5]

```bash
npx tsc --init
```

**Verify**: `ls tsconfig.json` → file exists

### 2. Set base options for all projects

These options should be in every tsconfig regardless of project type. [src2]

```json
{
  "compilerOptions": {
    "strict": true,
    "target": "es2022",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "moduleDetection": "force",
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true,
    "verbatimModuleSyntax": true,
    "noUncheckedIndexedAccess": true
  }
}
```

**Verify**: `npx tsc --noEmit` → no errors on clean project

### 3. Configure module resolution for your environment

Choose based on whether you use a bundler or run directly in Node.js. [src4]

```json
// For Vite, webpack, esbuild, Rollup:
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler",
    "noEmit": true
  }
}

// For pure Node.js (no bundler):
{
  "compilerOptions": {
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "outDir": "./dist"
  }
}
```

**Verify**: `npx tsc --showConfig | grep moduleResolution` → shows your chosen value

### 4. Add framework-specific options

Configure JSX for React, path aliases for large projects. [src1]

```json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"]
    }
  }
}
```

**Verify**: Create a file importing `@/utils/helper` → no red squiggles in editor

### 5. Configure library output (npm packages only)

Libraries need declaration files and source maps for consumers. [src1]

```json
{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}
```

**Verify**: `npx tsc && ls dist/` → `.js`, `.d.ts`, and `.d.ts.map` files present

### 6. Set up project references for monorepos

Use composite projects with references for independent compilation. [src5]

```json
// tsconfig.json (root)
{
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/ui" },
    { "path": "./packages/api" }
  ],
  "files": []
}

// packages/core/tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true
  },
  "include": ["src/**/*"]
}
```

**Verify**: `npx tsc --build` → builds all referenced projects in dependency order

## Code Examples

### Complete tsconfig for Vite + React + TypeScript

> Full script: [complete-tsconfig-for-vite-react-typescript.json](scripts/complete-tsconfig-for-vite-react-typescript.json) (32 lines)

```json
// tsconfig.json — Vite + React project
{
  "compilerOptions": {
    // Base (every project)
    "strict": true,
# ... (see full script)
```

### Complete tsconfig for Node.js + Express + TypeScript

> Full script: [complete-tsconfig-for-node-js-express-typescript.json](scripts/complete-tsconfig-for-node-js-express-typescript.json) (29 lines)

```json
// tsconfig.json — Node.js backend project
{
  "compilerOptions": {
    // Base
    "strict": true,
# ... (see full script)
```

### Complete tsconfig for npm library

> Full script: [complete-tsconfig-for-npm-library.json](scripts/complete-tsconfig-for-npm-library.json) (27 lines)

```json
// tsconfig.json — npm library (dual CJS/ESM)
{
  "compilerOptions": {
    // Base
    "strict": true,
# ... (see full script)
```

## Anti-Patterns

### Wrong: Skipping strict mode on new projects

```json
// ❌ BAD — silent any, null bugs everywhere
{
  "compilerOptions": {
    "strict": false,
    "target": "es5"
  }
}
```

### Correct: Always enable strict

```json
// ✅ GOOD — catches bugs at compile time
{
  "compilerOptions": {
    "strict": true,
    "target": "es2022"
  }
}
```

### Wrong: Using "moduleResolution": "node" with a bundler

```json
// ❌ BAD — "node" is legacy, misses package.json exports
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "node"
  }
}
```

### Correct: Use "bundler" with bundlers, "nodenext" with Node

```json
// ✅ GOOD — "bundler" supports exports, no extension requirement
{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "bundler"
  }
}
```

### Wrong: Setting paths without bundler alias config

```json
// ❌ BAD — TS resolves types but emitted JS still has @/ imports
{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}
// Runtime error: Cannot find module '@/utils/helper'
```

### Correct: Configure paths in both tsconfig AND bundler

```json
// ✅ GOOD — tsconfig.json
{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}
// ALSO add to vite.config.ts:
// resolve: { alias: { "@": path.resolve(__dirname, "src") } }
```

## Common Pitfalls

- **verbatimModuleSyntax breaks CJS imports**: If your project emits CommonJS, `import type` must use `import type =` syntax. Fix: only use `verbatimModuleSyntax` with ESM output or `module: "nodenext"`. [src3]
- **paths aliases not working at runtime**: TypeScript resolves types but does not rewrite paths. Fix: add `vite-tsconfig-paths` (Vite) or `tsconfig-paths` (Node.js) or configure bundler aliases. [src1]
- **incremental creates stale tsbuildinfo**: Old cache causes phantom errors. Fix: delete `tsconfig.tsbuildinfo` and rebuild: `rm tsconfig.tsbuildinfo && npx tsc`. [src6]
- **lib missing DOM types**: Server-side code should not include `"dom"`. Fix: set `"lib": ["es2022"]` for Node.js, `"lib": ["es2022", "dom", "dom.iterable"]` for browser. [src1]
- **exactOptionalPropertyTypes too strict for team**: Requires `undefined` to be explicitly passed. Fix: only enable in libraries or with experienced teams — start with `strict: true` alone. [src2]
- **outDir and rootDir mismatch**: Compiled output directory structure is wrong. Fix: `rootDir` must be the common ancestor of all source files, `outDir` is where compiled files go. [src5]

## Diagnostic Commands

```bash
# Show fully resolved tsconfig (inherited + defaults)
npx tsc --showConfig

# Type-check without emitting files
npx tsc --noEmit

# List files that would be compiled
npx tsc --listFiles

# Show why a module was resolved to a path
npx tsc --traceResolution | grep "module-name"

# Check TypeScript version
npx tsc --version

# Build with verbose diagnostics
npx tsc --extendedDiagnostics
```

## Version History & Compatibility

| Version | Status | Key Additions | Notes |
|---|---|---|---|
| TS 5.7 | Current | — | Stable; fully supports all options below |
| TS 5.6 | Current | `--noUncheckedSideEffectImports` | Minor strictness addition |
| TS 5.5 | Stable | `isolatedDeclarations`, config extends arrays | `extends` can be an array of configs |
| TS 5.4 | Stable | `verbatimModuleSyntax` finalized | Replaces `importsNotUsedAsValues` |
| TS 5.0 | LTS | `moduleResolution: "bundler"`, decorators | First version with bundler resolution |
| TS 4.x | EOL | — | Upgrade to 5.x; `moduleResolution: "node"` only |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Any TypeScript project | Using Deno (built-in TS support) | `deno.json` compilerOptions |
| Need precise type checking | Quick prototype that will be discarded | `// @ts-nocheck` or plain JS |
| Building npm libraries | Using Bun exclusively | `bunfig.toml` + minimal tsconfig |
| Monorepo with shared types | Single-file script | `npx tsx script.ts` (no config needed) |

## Important Caveats

- `moduleResolution: "bundler"` requires `module: "esnext"` or `"preserve"` — cannot be combined with `"commonjs"` or `"node16"`
- `verbatimModuleSyntax` replaces the older `importsNotUsedAsValues` and `preserveValueImports` — do not use the old options
- TypeScript path aliases (`paths`) are purely a type-resolution feature — they do NOT affect the emitted JavaScript
- `composite: true` requires `declaration: true` and disallows `noEmit: true`

## Related Units

- [ESLint + Prettier Configuration Reference](/software/devops/eslint-prettier-config/2026)
- [Vite Configuration Reference](/software/devops/vite-configuration/2026)
- [Jest Testing Configuration Reference](/software/devops/jest-configuration/2026)
