Skip to content
Theory · A TypeScript project · lesson 5 of 10

tsconfig.json

The house rules hang on the wall: where to leave your shoes, when to turn the music off. Nobody retells them to every guest. The rules are the same for everyone, and anyone can read them.

A TypeScript project also has rules for tsc: check strictly, write the JavaScript into a separate folder, write no files while the code has errors. You can type them as flags every time:

TEXT
$ tsc --strict --noEmitOnError --outDir dist src/main.ts

Such a command has to be typed every time, and typos creep in. And a colleague runs tsc with other flags and gets a different result. That is why the rules are written down once, in a tsconfig.json file at the root of the project.

The tsconfig.json file

Let's put the sources into a src folder and tsconfig.json next to it:

TEXT
shop/
    tsconfig.json
    src/
        format.ts
        main.ts

Here are the project's rules:

TEXT
{
    "compilerOptions": {
        "target": "es2022",
        "module": "nodenext",
        "strict": true,
        "rootDir": "src",
        "outDir": "dist",
        "noEmitOnError": true
    },
    "include": ["src"]
}

This is JSON: an object as in JavaScript, except that the keys are always in double quotes. compilerOptions gathers the compiler's settings, and include says which files to check.

Now tsc is run without file names:

TEXT
$ tsc
$ node dist/main.js
100.00

Without file names tsc finds tsconfig.json in the current folder, reads the rules and compiles everything listed in include. The JavaScript appears in the dist folder: dist/main.js and dist/format.js.

Compiler settings

target

target is the JavaScript version tsc writes. If that version lacks some language feature, tsc rewrites the code without it. The ?? operator appeared in JavaScript in 2020. So with "target": "es2019" the line city ?? "-" turns into city !== null && city !== void 0 ? city : "-" (void 0 evaluates to undefined in JavaScript), while with "es2022" it stays as it is.

module

module is the form in which tsc writes import and export. The value "nodenext" means "the way Node.js will read them".

strict

strict turns on strict mode. Since TypeScript 6.0 it is on even without this line, but it is written so that the rule is visible in the file. Strict mode is a group of checks, and each has its own name:

  • strictNullChecks: null and undefined are separate types, and null cannot go into a variable of type string;
  • noImplicitAny: a parameter without a type is error TS7006 instead of silently getting the type any.

One check can be turned off without touching the others: "noImplicitAny": false next to "strict": true. In this course every strict-mode check is on.

rootDir and outDir

rootDir is the folder with the sources, and outDir is the folder where tsc writes the JavaScript. src/main.ts becomes dist/main.js. When tsconfig.json sets outDir and the sources sit in a subfolder, TypeScript 7 requires you to name it in rootDir. Without that line it stops:

TEXT
error TS5011: The common source directory of 'tsconfig.json' is './src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.

noEmitOnError

noEmitOnError forbids writing JavaScript while the code has errors. It is the same --noEmitOnError flag, only written once for the whole project.

include

include is the list of folders and files tsc checks. ["src"] means "every .ts file in the src folder and in the folders inside it".

An interview question

Interviewers often ask what tsconfig.json is and what strict does. The answer: it is the file with the tsc settings for the whole project, and strict turns on a group of strict checks, among them strictNullChecks and noImplicitAny.

When tsc reads the rules

Here the picture of rules on the wall stops working. The house rules apply to everyone who walks in. tsc reads tsconfig.json only when it is run without file names.

Common mistake

Running tsc with a file name out of habit, in a folder that has a tsconfig.json:

TEXT
$ tsc src/main.ts
error TS5112: tsconfig.json is present but will not be loaded if files are specified on commandline. Use '--ignoreConfig' to skip this error.

With a file name tsc does not read tsconfig.json, and the file would be checked with the default settings rather than by the project's rules. TypeScript 7 does not let this mistake pass silently and stops with this message.

Run tsc without file names. If you need to check one file without the project's rules, add the flag from the message: tsc --ignoreConfig src/main.ts. Then main.js appears next to main.ts rather than in dist.

Key points

  • tsconfig.json holds the tsc rules for the project: the settings in compilerOptions and the list of files in include.
  • tsc without file names reads tsconfig.json and compiles the whole project.
  • strict turns on a group of checks, among them strictNullChecks and noImplicitAny; since TypeScript 6.0 it is on by default.
  • When a tsconfig.json is next to it, tsc with a file name stops with error TS5112 in TypeScript 7.