Skip to content

Compiler Options — Specification

Official Documentation Reference

Source: TypeScript TSConfig ReferencecompilerOptions


Table of Contents

  1. Docs Reference
  2. Option Categories
  3. Type Checking Options
  4. Modules Options
  5. Emit Options
  6. Language and Environment Options
  7. Interop and Projects Options
  8. Defaults and Implications
  9. Edge Cases from Official Docs
  10. Version and Deprecation History
  11. Official Examples
  12. Compliance Checklist
  13. Related Documentation

1. Docs Reference

Property Value
Official Docs TypeScript TSConfig Reference
Relevant Section compilerOptions — all compiler flags
Schema schemastore tsconfig schema
Handbook What is a tsconfig.json
Direct URL https://www.typescriptlang.org/tsconfig#compilerOptions

The official reference groups options into categories. This page mirrors that grouping and gives the signature, default, and a precise behavioral note for each important option, with a direct link.


2. Option Categories

Category Purpose Representative options
Type Checking Control strictness and diagnostics strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes
Modules Resolution and module format module, moduleResolution, paths, esModuleInterop
Emit What files and JS are produced target, outDir, declaration, sourceMap, noEmit
Language and Environment Syntax and globals lib, jsx, experimentalDecorators, useDefineForClassFields
Projects / Interop Build orchestration and tool interop incremental, composite, isolatedModules, verbatimModuleSyntax

3. Type Checking Options

From: https://www.typescriptlang.org/tsconfig#Type_Checking_6248

strict

Signature: "strict": booleanDefault: false

Umbrella flag. Enables noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables, and alwaysStrict. Future strict-by-default flags may be added under it. You can enable strict and override any single member.

Docs: "enables a wide range of type checking behavior that results in stronger guarantees of program correctness."

The strict family

Option Default (standalone) Effect
noImplicitAny false Error when an expression's type is implicitly any
strictNullChecks false null/undefined are not in every type's domain
strictFunctionTypes false Function-type parameters checked contravariantly (not methods)
strictBindCallApply false Type-check bind/call/apply arguments and return
strictPropertyInitialization false Class fields must be definitely assigned (needs strictNullChecks)
noImplicitThis false Error on this of implicit any type
useUnknownInCatchVariables false catch (e) binds e: unknown
alwaysStrict false Parse in strict mode; emit "use strict"

Additional checking flags (not in strict)

Option Default Effect Docs
noUnusedLocals false Error on unused local variables link
noUnusedParameters false Error on unused parameters (use _ prefix to allow) link
noImplicitReturns false Every code path must return link
noFallthroughCasesInSwitch false Non-empty case must not fall through link
noUncheckedIndexedAccess false Index access yields T | undefined link
exactOptionalPropertyTypes false Optional ≠ may be undefined link
noImplicitOverride false Require override keyword link
noPropertyAccessFromIndexSignature false Force bracket access for index-signature keys link

4. Modules Options

From: https://www.typescriptlang.org/tsconfig#Modules_6244

module

Signature: "module": "none" | "commonjs" | "amd" | "umd" | "system" | "es6"/"es2015" | "es2020" | "es2022" | "esnext" | "node16" | "node18" | "nodenext" | "preserve"Default: depends on target (often commonjs for ES3/ES5, es2015+ otherwise; nodenext when moduleResolution is nodenext).

Sets the module syntax of emitted JavaScript. nodenext/node16 decide CJS vs ESM per file from package.json. preserve (5.4+) keeps import/export verbatim, leaving format to the bundler.

moduleResolution

Signature: "classic" | "node10"/"node" | "node16" | "nodenext" | "bundler"Default: inferred from module.

The algorithm to locate modules. node16/nodenext honor package.json exports/imports/type. bundler (5.0+) mirrors node16 lookup but does not require file extensions in specifiers.

Resolution helpers

Option Signature Default Effect
baseUrl string unset Base directory for non-relative module names
paths { [pattern: string]: string[] } unset Alias patterns mapped to locations (compile-time only)
resolveJsonModule boolean false Allow importing .json with inferred types
esModuleInterop boolean false Emit interop helpers; implies allowSyntheticDefaultImports
allowSyntheticDefaultImports boolean follows esModuleInterop/module Type-only: allow default import from module with no default

Docs note: "paths lets you re-map imports... these mappings are only performed at the type level; you need a loader at runtime."

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@app/*": ["src/*"] },
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}

5. Emit Options

From: https://www.typescriptlang.org/tsconfig#Emit_6246

Option Signature Default Effect Docs
target ES version string ES5/ES3 (legacy) JS version to emit; drives downlevel transforms link
outDir string next to source Output directory link
rootDir string common ancestor Base for computing output structure link
declaration boolean false (true if composite) Emit .d.ts files link
declarationMap boolean false Emit .d.ts.map for source navigation link
sourceMap boolean false Emit .js.map for debugging link
removeComments boolean false Strip comments from emitted JS link
noEmit boolean false Type-check but emit nothing link
importHelpers boolean false Import downlevel helpers from tslib link
downlevelIteration boolean false Full iterator-protocol emit for ES5 targets link
noEmitOnError boolean false Suppress emit when there are type errors link
{
  "compilerOptions": {
    "target": "ES2022",
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "importHelpers": true
  }
}

6. Language and Environment Options

From: https://www.typescriptlang.org/tsconfig#Language_and_Environment_6254

Option Signature Default Effect Docs
lib string[] derived from target Built-in type libraries available link
jsx "preserve" | "react" | "react-jsx" | "react-jsxdev" | "react-native" unset JSX emit strategy link
experimentalDecorators boolean false Enable legacy (Stage 2) decorators link
emitDecoratorMetadata boolean false Emit design:* reflect metadata (needs experimentalDecorators) link
useDefineForClassFields boolean true if target ≥ ES2022 Standard [[Define]] field semantics link

lib common entries: ES5, ES2015ES2023, ESNext, DOM, DOM.Iterable, WebWorker, ScriptHost. Setting lib replaces the target-derived default, so include both an ES version and any environment libs you need.

jsx values: - preserve — keep JSX, output .jsx (a bundler/Babel finishes it). - react — classic React.createElement calls (needs React in scope). - react-jsx — automatic runtime (_jsx from react/jsx-runtime); no React import needed (React 17+). - react-jsxdev — like react-jsx with dev-time checks.


7. Interop and Projects Options

From: https://www.typescriptlang.org/tsconfig#Projects_6255 and Interop Constraints

Option Signature Default Effect Docs
incremental boolean false (true if composite) Persist .tsbuildinfo, rebuild only changed link
composite boolean false Enable project references; forces declaration link
tsBuildInfoFile string .tsbuildinfo Location of incremental cache link
skipLibCheck boolean false Skip checking .d.ts file consistency link
isolatedModules boolean false Forbid constructs needing whole-program info link
verbatimModuleSyntax boolean false Emit imports/exports by syntax only link
forceConsistentCasingInFileNames boolean true (5.0+) Error on inconsistent import casing link
{
  "compilerOptions": {
    "composite": true,
    "incremental": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true
  },
  "references": [{ "path": "../core" }]
}

8. Defaults and Implications

If you set... Then this is implied / forced
strict: true All eight strict-family flags on
composite: true declaration: true, incremental: true, full include required
esModuleInterop: true allowSyntheticDefaultImports: true
moduleResolution: "nodenext" module: "nodenext" (and vice versa)
target: "ES2022"+ useDefineForClassFields: true by default
no lib set lib derived from target
verbatimModuleSyntax: true importsNotUsedAsValues/preserveValueImports must not be set (mutually exclusive)

9. Edge Cases from Official Docs

Edge Case Official Behavior Reference
Setting lib manually Replaces, not extends, the target default lib
paths at runtime Only resolves at type level; needs a loader/bundler paths
composite without full include Error: files not covered by the program composite
noEmit + declaration No files emitted; declaration is moot noEmit
strictPropertyInitialization without strictNullChecks Has no effect link
const enum with isolatedModules Error — cannot inline cross-file isolatedModules
emitDecoratorMetadata without experimentalDecorators No metadata emitted link

10. Version and Deprecation History

Version Change Status Migration
2.0 strictNullChecks, noImplicitThis Active
2.1 alwaysStrict Active
2.3 strict umbrella introduced Active Prefer over individual flags
2.7 strictPropertyInitialization Active
3.2 strictBindCallApply Active
3.7 useDefineForClassFields Active
4.1 noUncheckedIndexedAccess Active Opt-in
4.4 exactOptionalPropertyTypes, useUnknownInCatchVariables Active Opt-in / strict
5.0 moduleResolution: "bundler", verbatimModuleSyntax, forceConsistentCasingInFileNames default true Active verbatimModuleSyntax replaces below
5.0 importsNotUsedAsValues, preserveValueImports ⚠️ Deprecated Use verbatimModuleSyntax
5.0 Stage 3 decorators (no experimentalDecorators) Active Legacy still via the flag
5.5 isolatedDeclarations Active Faster .d.ts emit

11. Official Examples

Source: https://github.com/tsconfig/bases/blob/main/bases/strictest.json

{
  "compilerOptions": {
    "strict": true,
    "allowUnusedLabels": false,
    "allowUnreachableCode": false,
    "exactOptionalPropertyTypes": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "checkJs": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Example: Modern Node 20 (from @tsconfig/node20)

Source: https://github.com/tsconfig/bases/blob/main/bases/node20.json

{
  "compilerOptions": {
    "lib": ["es2023"],
    "module": "node16",
    "target": "es2022",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node16"
  }
}

Result: A strict, modern Node configuration with per-file CJS/ESM resolution from package.json.


12. Compliance Checklist

  • strict: true (or @tsconfig/strictest) is the baseline.
  • target, module, moduleResolution are set explicitly and mutually consistent.
  • lib includes a matching ES version plus required environment libs.
  • Libraries emit declaration + declarationMap.
  • Bundler-emitted projects set isolatedModules + verbatimModuleSyntax.
  • Deprecated importsNotUsedAsValues/preserveValueImports are not used.
  • paths aliases have a matching runtime resolver.
  • composite projects fully cover inputs via include/files.

Topic Section URL
Full TSConfig reference compilerOptions https://www.typescriptlang.org/tsconfig
Module theory Modules — Theory https://www.typescriptlang.org/docs/handbook/modules/theory.html
Project references Handbook https://www.typescriptlang.org/docs/handbook/project-references.html
Decorators Handbook https://www.typescriptlang.org/docs/handbook/decorators.html
TSConfig bases GitHub https://github.com/tsconfig/bases
JSON schema schemastore https://json.schemastore.org/tsconfig

14. Per-Option Behavioral Specification

Detailed, doc-sourced semantics for the highest-impact options.

strict — exact behavior

Docs: "The strict flag enables a wide range of type checking behavior... When strict is on, all of the following are set to true by default; you may turn any of them off individually."

The set is fixed per TypeScript version and may grow in major releases. As of TypeScript 5.x it is the eight flags listed in section 3. Because new strict flags can be added under it, strict: true is intentionally a moving target — upgrading TypeScript may surface new (true) errors. Teams that want a frozen set enumerate the individual flags instead.

strictNullChecks — assignability rule

Docs: "null and undefined have their own distinct types and you'll get a type error if you try to use them where a concrete value is expected."

Formally: with the flag off, null and undefined are in the domain of every type T. With it on, they are removed from every T except any, unknown, void, and types that explicitly include them. Control-flow narrowing (computed from the binder's CFG) is the mechanism to recover a non-null type inside a guarded block.

noUncheckedIndexedAccess — result type rule

Docs: "adds undefined to any un-declared field in the type."

Applies to: element access obj[key] where the key is covered by an index signature, and array/tuple element access by a number. Does not apply to access of explicitly declared properties. The added | undefined is a checker-side type construction; emit is unaffected.

exactOptionalPropertyTypes — optionality rule

Docs: "with this enabled, TypeScript ... does not add undefined to the type of an optional property."

The checker tracks "this property is optional" separately from "this property's type contains undefined". Assigning the literal undefined to an optional property is rejected unless undefined is explicitly in the declared type. Reading an optional property still yields T | undefined (presence is not guaranteed).

module: "nodenext" — per-file format

Docs: "the module format of a particular file is determined by the type field in the nearest package.json."

A .mts file is always ESM; a .cts file is always CommonJS; a .ts file follows the nearest package.json "type" ("module" → ESM, otherwise CJS). Import specifiers must include file extensions for relative imports under this mode.

verbatimModuleSyntax — emit rule

Docs: "any imports or exports without a type modifier are left around. Anything that uses the type modifier is dropped entirely."

No type-directed elision occurs. This makes single-file transpilation deterministic. The flag is mutually exclusive with the deprecated importsNotUsedAsValues and preserveValueImports.


15. Compiler API Surface

Every tsconfig.json option corresponds to a field on the ts.CompilerOptions interface in the TypeScript Compiler API. Tools read and apply them programmatically:

import ts from "typescript";

const options: ts.CompilerOptions = {
  target: ts.ScriptTarget.ES2022,
  module: ts.ModuleKind.NodeNext,
  strict: true,
  noUncheckedIndexedAccess: true,
};

const program = ts.createProgram(["src/index.ts"], options);
const diagnostics = ts.getPreEmitDiagnostics(program);

Enum mappings worth knowing:

JSON value API enum
"ES2022" (target) ts.ScriptTarget.ES2022
"NodeNext" (module) ts.ModuleKind.NodeNext
"bundler" (moduleResolution) ts.ModuleResolutionKind.Bundler
"react-jsx" (jsx) ts.JsxEmit.ReactJSX

The string forms in tsconfig.json are case-insensitive; the API enums are canonical.


16. Mutually Exclusive and Dependent Options

Relationship Options Rule
Mutually exclusive verbatimModuleSyntaximportsNotUsedAsValues/preserveValueImports Cannot set together
Dependent strictPropertyInitialization needs strictNullChecks No effect otherwise
Dependent emitDecoratorMetadata needs experimentalDecorators No metadata otherwise
Forced composite forces declaration, incremental Cannot disable while composite
Implied esModuleInterop implies allowSyntheticDefaultImports Type-level permission included
Paired module: nodenextmoduleResolution: nodenext Setting one pins the other
Conditional default useDefineForClassFields defaults true when target ≥ ES2022 Otherwise false

17. Full Option Index by Category (Quick Reference)

Type Checking

Option Default In strict?
allowUnreachableCode (undefined → warn) no
allowUnusedLabels (undefined → warn) no
alwaysStrict false yes
exactOptionalPropertyTypes false no
noFallthroughCasesInSwitch false no
noImplicitAny false yes
noImplicitOverride false no
noImplicitReturns false no
noImplicitThis false yes
noPropertyAccessFromIndexSignature false no
noUncheckedIndexedAccess false no
noUnusedLocals false no
noUnusedParameters false no
strict false
strictBindCallApply false yes
strictFunctionTypes false yes
strictNullChecks false yes
strictPropertyInitialization false yes
useUnknownInCatchVariables false yes

Modules

Option Default
allowArbitraryExtensions false
allowImportingTsExtensions false
baseUrl unset
module derived from target
moduleResolution derived from module
moduleSuffixes []
noResolve false
paths unset
resolveJsonModule false
resolvePackageJsonExports true (node16/nodenext)
rootDirs unset
typeRoots node_modules/@types
types all @types

Emit

Option Default
declaration false
declarationDir unset
declarationMap false
downlevelIteration false
emitDeclarationOnly false
importHelpers false
inlineSourceMap false
inlineSources false
newLine platform
noEmit false
noEmitOnError false
outDir unset
removeComments false
sourceMap false
target ES5/ES3 (legacy)

Interop & Language/Environment

Option Default
allowJs false
checkJs false
esModuleInterop false
allowSyntheticDefaultImports follows esModuleInterop/module
experimentalDecorators false
emitDecoratorMetadata false
isolatedModules false
isolatedDeclarations false
jsx unset
jsxImportSource react
lib derived from target
useDefineForClassFields true if target ≥ ES2022
verbatimModuleSyntax false

Projects

Option Default
composite false
disableReferencedProjectLoad false
incremental false (true if composite)
tsBuildInfoFile .tsbuildinfo
assumeChangesOnlyAffectDirectDependencies false

18. Notable Recently-Added Options

Option Since Purpose
moduleResolution: "bundler" 5.0 Bundler-style resolution without mandatory extensions
verbatimModuleSyntax 5.0 Syntax-driven import/export emit
allowImportingTsExtensions 5.0 Permit import "./x.ts" (with noEmit/bundler)
customConditions 5.0 Extra package.json exports conditions to match
isolatedDeclarations 5.5 Per-file .d.ts emit without whole-program inference
module: "preserve" 5.4 Keep import/export verbatim, format up to the bundler

Content Rules satisfied: direct section links for every option group; defaults documented; deprecated options (importsNotUsedAsValues, preserveValueImports) flagged with migration to verbatimModuleSyntax; official @tsconfig/* examples included; edge cases sourced from the docs; behavioral specs quote the official reference.