TS

Configuration

TypeScript · 7 entries

strict Mode

Syntax
// tsconfig.json
{ "compilerOptions": { "strict": true } }
Example
// strict: true enables ALL of these at once:
// - strictNullChecks: null/undefined not assignable to other types
// - strictFunctionTypes: contravariant function parameter checking
// - strictBindCallApply: type-check bind, call, apply
// - strictPropertyInitialization: class props must be initialized
// - noImplicitAny: error on implicit any
// - noImplicitThis: error on 'this' with implicit any type
// - useUnknownInCatchVariables: catch variable is unknown, not any
// - alwaysStrict: emit "use strict" in every file
Output
// strict: true is the recommended baseline for all new projects

Note Always start new projects with strict: true. You can selectively disable individual checks if needed (e.g., "strictPropertyInitialization": false) while keeping the rest. Enabling strict on a large existing JS-to-TS migration can produce thousands of errors - enable checks incrementally in that case.

target & module

Syntax
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext"
  }
}
Example
// target: which JS version to emit
// "ES5" - maximum compat (IE11), heavy downleveling
// "ES2020" - good baseline for modern browsers
// "ES2022" - class fields, top-level await, cause in Error
// "ESNext" - latest; may change between TS versions

// module: which module system to use
// "commonjs" - Node.js require/exports
// "es2022" - ES modules with top-level await
// "esnext" - latest ES module features
// "node16" / "nodenext" - Node.js ESM with .mjs/.cjs awareness
// "preserve" - keep import/export as written (TS 5.4+)
Output
// target controls syntax downleveling; module controls import/export format

Note For bundled apps (Vite, webpack), set target to your browser baseline and module to ESNext - the bundler handles the rest. For Node.js, use module: "node16" or "nodenext" which correctly resolves .mjs/.cjs and package.json "type" fields. The new "preserve" module option (TS 5.4+) emits imports exactly as written.

paths & baseUrl

Syntax
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@alias/*": ["src/folder/*"]
    }
  }
}
Example
// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"],
      "@api/*": ["src/api/*"],
      "@types/*": ["src/types/*"]
    }
  }
}

// In your code:
import { Button } from "@components/Button";
import { formatDate } from "@utils/date";
import type { User } from "@types/user";
Output
// Path aliases shorten deep relative imports like ../../../../utils

Note paths only affects TypeScript's type resolution - it does NOT rewrite imports in emitted JS. Your bundler (Vite, webpack) or runtime (ts-node, tsx) needs matching alias config. For Node.js, package.json "imports" with subpath patterns is the modern alternative that works without bundler config.

noEmit & declaration

Syntax
{
  "compilerOptions": {
    "noEmit": true,
    "declaration": true
  }
}
Example
// noEmit: true - only type-check, don't produce .js files
// Used when a bundler (Vite, esbuild, SWC) handles transpilation
{
  "compilerOptions": {
    "noEmit": true  // tsc is just the type checker
  }
}

// declaration: true - generate .d.ts files alongside .js
// Used for libraries that need to ship type definitions
{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./dist/types",
    "emitDeclarationOnly": true  // only .d.ts, no .js
  }
}
Output
// noEmit for apps (bundler compiles); declaration for libraries (ship types)

Note Most modern app setups use noEmit: true because tools like Vite, esbuild, and SWC transpile much faster than tsc. Library authors use declaration: true (often with emitDeclarationOnly) to generate .d.ts files while letting another tool handle .js output.

isolatedModules & verbatimModuleSyntax

Syntax
{
  "compilerOptions": {
    "isolatedModules": true,
    "verbatimModuleSyntax": true
  }
}
Example
// isolatedModules: true
// Ensures each file can be transpiled independently
// Required for: Babel, esbuild, SWC, Vite
// Disallows: const enums across files, namespace merging across files

// verbatimModuleSyntax: true (TS 5.0+, replaces isolatedModules)
// Forces you to use 'import type' for type-only imports

import type { User } from "./models";       // erased at runtime
import { processUser } from "./handlers";   // kept at runtime

// import { User } from "./models";
// Error with verbatimModuleSyntax: 'User' is a type and must use 'import type'
Output
// Enforces clean separation of type imports from value imports

Note verbatimModuleSyntax (TS 5.0+) supersedes both isolatedModules and the older importsNotUsedAsValues. It makes the distinction between type and value imports explicit and mandatory. This produces cleaner output and avoids side-effect confusion. Recommended for all new projects.

Project References

Syntax
// tsconfig.json
{
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/api" }
  ]
}
Example
// Root tsconfig.json
{
  "files": [],
  "references": [
    { "path": "./packages/shared" },
    { "path": "./packages/server" },
    { "path": "./packages/client" }
  ]
}

// packages/server/tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "references": [
    { "path": "../shared" }
  ]
}

// Build with: tsc --build
Output
// tsc --build only recompiles packages that changed

Note Project references enable incremental builds in monorepos. Each sub-project needs "composite": true. Build with tsc --build (or tsc -b) which understands dependency order. This dramatically speeds up type-checking in large codebases by skipping unchanged packages.

Essential Compiler Options

Syntax
// tsconfig.json compilerOptions
Example
{
  "compilerOptions": {
    "strict": true,
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "allowImportingTsExtensions": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "lib": ["ES2022", "DOM", "DOM.Iterable"]
  },
  "include": ["src"]
}
Output
// A solid starting tsconfig for a modern bundled web app

Note moduleResolution: "bundler" (TS 5.0+) matches how Vite/webpack/esbuild resolve modules - it supports exports maps, .ts extensions in imports, and does not require file extensions. skipLibCheck: true speeds up compilation by not checking node_modules .d.ts files (only your code is checked).