|$ curl https://forge-ai.dev/api/markdown?path=docs/typescript/config
$cat docs/typescript-—-tsconfig-configuration.md
updated Recently·14 min read·published

TypeScript — tsconfig Configuration

TypeScriptIntermediate
Introduction

tsconfig.json configures the TypeScript compiler (tsc). It defines which files to compile, how to compile them, and what strictness level to enforce. Understanding these options is essential for any TypeScript project.

Basic Setup

A minimal tsconfig.json specifies compiler options and which files to include. The compilerOptions object is the heart of the configuration.

tsconfig.json
JSON
1{
2 "compilerOptions": {
3 "target": "ES2020",
4 "module": "ESNext",
5 "moduleResolution": "bundler",
6 "strict": true,
7 "esModuleInterop": true,
8 "skipLibCheck": true,
9 "forceConsistentCasingInFileNames": true,
10 "outDir": "./dist",
11 "rootDir": "./src"
12 },
13 "include": ["src/**/*"],
14 "exclude": ["node_modules", "dist"]
15}

info

Run tsc --init to generate a tsconfig.json with all options documented. For new projects, start with strict: true and add exceptions only when needed.
Target & Module Settings

target determines the ECMAScript version your code compiles down to. module determines how module syntax (import/export) is transformed.

tsconfig.target.json
JSON
1{
2 "compilerOptions": {
3 "target": "ES2022",
4 "module": "ESNext",
5 "lib": ["ES2022", "DOM", "DOM.Iterable"],
6 "moduleResolution": "bundler"
7 }
8}
targetDescription
ES5Legacy — transforms async/await, classes, etc.
ES2017Native async/await support
ES2020Adds BigInt, optional chaining, nullish coalescing
ES2022Top-level await, class fields, error cause
ESNextLatest features — use only when target runtime supports it
moduleDescription
CommonJSNode.js require/module.exports
ESNextPreserves import/export — let the bundler handle it
Node16 / NodeNextNode.js ESM with .mjs/.cjs resolution
UMDUniversal module definition (browser + Node)

best practice

For modern projects, use target: "ES2022", module: "ESNext", and moduleResolution: "bundler". Let your bundler (Vite, webpack, esbuild) handle the module transformation.
Strict Checks

The strict flag enables a group of strict type-checking options. You can also enable each individually for finer control.

tsconfig.strict.json
JSON
1{
2 "compilerOptions": {
3 "strict": true,
4 // Equivalent to enabling all of:
5 "noImplicitAny": true,
6 "strictNullChecks": true,
7 "strictFunctionTypes": true,
8 "strictBindCallApply": true,
9 "strictPropertyInitialization": true,
10 "noImplicitThis": true,
11 "useUnknownInCatchVariables": true
12 }
13}
OptionWhat it does
strictNullChecksnull/undefined are distinct types — must handle explicitly
noImplicitAnyError when TypeScript can't infer a type (no hidden any)
strictFunctionTypesFunction parameter types are checked contravariantly
strictPropertyInitializationClass properties must be initialized in constructor
noImplicitThisError when this has an implicit any type
useUnknownInCatchVariablesCatch clause variables are unknown instead of any

warning

strictNullChecks is the single most impactful strict option. Disabling it lets null and undefinedbe assigned to any type, which defeats most of TypeScript's safety guarantees. Never disable it in new projects.
Module Resolution & Path Aliases

Module resolution determines how TypeScript finds imported modules. paths and baseUrl let you create import aliases instead of relative paths.

tsconfig.paths.json
JSON
1{
2 "compilerOptions": {
3 "moduleResolution": "bundler",
4 "baseUrl": ".",
5 "paths": {
6 "@/*": ["./src/*"],
7 "@components/*": ["./src/components/*"],
8 "@utils/*": ["./src/utils/*"],
9 "@lib/*": ["./src/lib/*"]
10 }
11 }
12}
aliases.ts
TypeScript
1// Without paths — verbose relative imports
2import { Button } from "../../../components/Button";
3import { formatDate } from "../../../utils/date";
4import { db } from "../../../lib/database";
5
6// With paths — clean absolute-style imports
7import { Button } from "@components/Button";
8import { formatDate } from "@utils/date";
9import { db } from "@lib/database";
10
11// Wildcard patterns match any depth
12import { helper } from "@utils/helpers/deep/module";

best practice

When using paths, your bundler must also be configured to resolve them. Vite, webpack, and esbuild each have their own path alias configuration. TypeScript's paths only affects the type checker, not the actual module resolution.
Output Configuration

These options control what files TypeScript emits and where.

tsconfig.output.json
JSON
1{
2 "compilerOptions": {
3 "outDir": "./dist",
4 "rootDir": "./src",
5 "declaration": true,
6 "declarationMap": true,
7 "sourceMap": true,
8 "removeComments": false,
9 "noEmit": false,
10 "isolatedModules": true
11 }
12}
OptionDescription
outDirOutput directory for compiled files
rootDirRoot directory for source files — controls output directory structure
declarationEmit .d.ts declaration files
declarationMapEmit .d.ts.map files for declaration source maps
sourceMapEmit .js.map source map files
isolatedModulesEnsure each file can be transpiled independently (required by esbuild/swc)
noEmitType-check only — don't emit output files
Source Maps

Source maps let you debug your original TypeScript code in browser DevTools or Node.js debuggers. They map compiled JavaScript back to your source files.

tsconfig.sourcemap.json
JSON
1{
2 "compilerOptions": {
3 "sourceMap": true,
4 "declarationMap": true,
5 "inlineSourceMap": false,
6 "inlineSources": true,
7 "sourceRoot": "./src"
8 }
9}
OptionDescription
sourceMapEmit separate .js.map files
inlineSourceMapEmbed source map as base64 in the .js file (single file, larger)
declarationMapSource maps for .d.ts files — enables go-to-definition into source
inlineSourcesInclude original .ts source in the source map

info

For library packages, always set declaration: true and declarationMap: true. This gives consumers of your library go-to-definition support that jumps directly to your source code.
Linter Integration

TypeScript provides compiler options that enforce code quality beyond type checking. These act as a lightweight linter directly in tsc.

tsconfig.lint.json
JSON
1{
2 "compilerOptions": {
3 "noUnusedLocals": true,
4 "noUnusedParameters": true,
5 "noImplicitReturns": true,
6 "noFallthroughCasesInSwitch": true,
7 "noUncheckedIndexedAccess": true,
8 "exactOptionalPropertyTypes": false,
9 "noPropertyAccessFromIndexSignature": false
10 }
11}
OptionDescription
noUnusedLocalsError on unused local variables
noUnusedParametersError on unused function parameters (prefix with _ to allow)
noImplicitReturnsError if a function doesn't explicitly return on all code paths
noFallthroughCasesInSwitchError on fallthrough cases in switch statements
noUncheckedIndexedAccessArray/object index access returns T | undefined
JSX Support

For React projects, configure JSX transformation to match your framework's expectations.

tsconfig.jsx.json
JSON
1{
2 "compilerOptions": {
3 "jsx": "react-jsx",
4 "jsxImportSource": "react"
5 }
6}
jsxDescription
react-jsxJSX transform for React 17+ (no import React needed)
react-jsxdevDevelopment mode JSX transform with extra debugging info
preserveKeep JSX in output — let a bundler handle transformation
react-nativeReact Native — preserves JSX with .jsx extension
Best Practices

These guidelines help you set up tsconfig for maintainable, type-safe projects.

Always use strict mode. Start with "strict": true in every project. It catches real bugs. If legacy code needs exceptions, use per-file // @ts-ignore comments temporarily.

Use isolatedModules for bundler compatibility. Modern bundlers (esbuild, swc, Vite) transpile files independently. isolatedModules: true ensures your code is compatible.

Extend from a shared base. Use extends to share config across packages in a monorepo. Keep strict: true in the base and only customize per-package options.

Separate tsconfig files by concern. Use tsconfig.base.json for shared options, tsconfig.app.json for app code, and tsconfig.test.json for tests with different lib/settings.

Don't skip libCheck. skipLibCheck: true skips checking declaration files. It speeds up compilation but hides type errors in third-party types. Enable it for CI speed, but review errors periodically.

$Blueprint — Engineering Documentation·Section ID: TS-CONF·Revision: 1.0