tsconfig.json это файл конфигурации проекта TypeScript. Когда вы запускаете tsc без аргументов, компилятор ищет его в текущей папке (затем в родительских), читает параметры из compilerOptions и проверяет файлы, перечисленные в include. Небольшой, но полный пример:
{
"compilerOptions": {
"target": "es2022",
"module": "nodenext",
"strict": true,
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["src"]
}
Эта конфигурация компилирует все файлы TypeScript из src в JavaScript в dist в виде кода ES2022 по правилам модулей Node.js, со всеми строгими проверками. npx tsc --init генерирует более длинный стартовый файл с комментарием к каждому параметру.
Файл имеет формат JSON с комментариями: допускаются комментарии //, комментарии /* */ и завершающие запятые.
Рекомендуемая стартовая конфигурация
Для приложения или скрипта на Node.js:
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"target": "es2024",
"lib": ["es2024"],
"module": "nodenext",
"types": ["node"],
"strict": true,
"noUncheckedIndexedAccess": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"sourceMap": true
},
"include": ["src"]
}
Для типов Node.js нужен npm install --save-dev @types/node. С module: "nodenext" поле "type" в package.json решает, будет ли файл .ts модулем ES ("type": "module") или CommonJS ("type": "commonjs", его записывает npm init -y). Для новых проектов с import и export используйте "type": "module".
Для кода, который собирает бандлер вроде Vite, esbuild или webpack, JavaScript пишет бандлер, а tsc только проверяет:
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022", "dom"],
"module": "preserve",
"noEmit": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"skipLibCheck": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
Стартовые шаблоны фреймворков (Vite, Next.js, Angular) генерируют собственный tsconfig.json. Начинайте с него, а не заменяйте его.
Важные параметры
| Параметр | Что делает | Значение по умолчанию в TypeScript 7 |
|---|---|---|
target | Версия JavaScript на выходе; новый синтаксис переписывается для старых целей | es2025 |
lib | Типы встроенных API, о которых знает проверка (Array.prototype.at, Map, document) | Соответствует target, плюс DOM |
module | Какой модульный код генерируется и какие правила модулей действуют | esnext |
moduleResolution | Как пути импорта ищутся на диске | nodenext или node16 с соответствующим module, иначе bundler |
strict | Включает всё семейство строгих проверок | true |
rootDir | Папка, структура которой повторяется в outDir | Папка, где лежит tsconfig.json |
outDir | Куда попадают файлы .js (и .d.ts) | Рядом с каждым исходным файлом |
include / exclude / files | Какие файлы входят в проект | Все файлы .ts внутри папки |
types | Какие пакеты @types загружаются без импорта | [], никакие |
noEmit | Только проверка, ничего не записывать | false |
declaration | Также записывать файлы объявлений типов .d.ts | false |
sourceMap | Записывать файлы .js.map для отладчиков | false |
esModuleInterop | Позволяет import x from "cjs-package" работать с пакетами CommonJS | true (выключить нельзя) |
skipLibCheck | Не проверять типы в файлах .d.ts, включая файлы в node_modules | false |
target и lib
target указывает, на какой версии JavaScript должен работать результат. Синтаксис новее целевой версии переписывается: с "target": "es2017" поле класса или ??= превращается в более старый код. Самая низкая цель, которую принимает TypeScript 7, это es2015 (es6); es5 удалена.
target не добавляет недостающие API времени выполнения. Описывать их это задача lib, а предоставлять их задача полифила. lib сообщает проверке типов, какие встроенные объекты и методы существуют. Его значение по умолчанию следует за target и включает также типы DOM браузера, поэтому document проходит проверку даже в проекте на Node.js, если вы не зададите lib сами. Использование метода из стандарта новее вашего lib это ошибка компиляции:
src/b.ts(1,24): error TS2550: Property 'toSorted' does not exist on type 'number[]'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2023' or later.
Запускаемые примеры в этой документации используют lib es2022, поэтому toSorted, Object.groupBy и новые методы Set в них недоступны.
module и moduleResolution
У module есть три разумных значения для нового кода:
nodenext: для кода, который запускает Node.js. Каждый файл считается ESM или CommonJS по расширению (.mts,.cts) или по полю"type"ближайшегоpackage.json, ровно так, как решает Node. Относительным импортам в модулях ES нужно расширение файла, причём пишется.js, хотя исходник это.ts:import { add } from "./math.js".moduleResolutionподстраивается автоматически.preserve: для кода, который обрабатывает бандлер. Импорты остаются как написаны, а разрешение идёт по правиламbundler, которые допускают импорты без расширений.esnext: обычный вывод модулей ES с разрешениемbundler. Это значение по умолчанию, еслиmoduleне задан.
Частая первая ошибка с конфигурацией из tsc --init возникает из-за того, что npm init -y записывает "type": "commonjs":
src/main.ts(1,10): error TS1295: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'.
Файл использует import, а package.json говорит, что проект на CommonJS. Замените "type" на "module". Импорты и экспорты подробно разобраны на странице о модулях.
strict и параметры проверки
"strict": true включает сразу группу проверок: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, strictBuiltinIteratorReturn, noImplicitThis и useUnknownInCatchVariables. В TypeScript 7 он включён по умолчанию и включён во всех запускаемых примерах здесь. Код для строгого режима сужает тип, прежде чем использовать значение, которого может не быть:
Без аннотации тип параметра вывести нельзя, и noImplicitAny сообщает об этом:
index.ts(2,17): error TS7006: Parameter 'n' implicitly has an 'any' type.
strict включает не все полезные проверки. Стоит добавить ещё две: noUncheckedIndexedAccess (элемент массива или значение по сигнатуре индекса имеет тип T | undefined) и exactOptionalPropertyTypes (необязательному свойству нельзя явно присвоить undefined); tsc --init включает обе. Стилевые проверки вроде noUnusedLocals, noImplicitReturns и noFallthroughCasesInSwitch по умолчанию выключены.
Какие файлы: include, exclude, rootDir, outDir
Без include или files проект содержит все файлы .ts, .tsx и .d.ts в папке и её подпапках. node_modules исключается всегда. outDir тоже исключается, но только пока вы не задали exclude: собственный список exclude заменяет это поведение по умолчанию, поэтому добавьте в него папку вывода. include и exclude принимают glob-шаблоны:
{
"include": ["src", "scripts/**/*.ts"],
"exclude": ["src/**/*.test.ts"]
}
exclude только фильтрует то, что нашёл include. Файл, который импортирует другой включённый файл, всё равно компилируется.
outDir это место для результатов, а rootDir это часть дерева исходников, которая в нём повторяется: с "rootDir": "./src" файл src/api/users.ts становится dist/api/users.js. Задавайте оба. По умолчанию rootDir это папка, где лежит tsconfig.json, поэтому если задать только outDir, а исходники лежат в src, TypeScript 7 остановится с ошибкой:
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.
Параметры вывода: noEmit, declaration, sourceMap
"noEmit": trueпревращаетtscв чистую проверку типов. Используйте его, когда JavaScript создаёт другой инструмент (бандлер,tsx, удаление типов в Node.js)."declaration": trueзаписывает файл.d.tsдля каждого модуля, то есть типы без кода. Он нужен библиотекам, чтобы их пользователи получали типы.declarationMapдобавляет карты для перехода к определению в исходнике.ts."sourceMap": trueзаписывает файлы.js.map, чтобы отладчики и трассировки стека указывали на строки.ts."noEmitOnError": trueничего не записывает, пока есть ошибки типов. Без негоtscсообщает об ошибках и всё равно записывает JavaScript.
types, esModuleInterop и skipLibCheck
types перечисляет пакеты @types, которые загружаются глобально, без импорта. В TypeScript 7 по умолчанию это пустой список, поэтому после npm install --save-dev @types/node добавьте ещё "types": ["node"]; иначе process и require останутся неизвестными (error TS2591: Cannot find name 'process'). Тестовые раннеры с глобальными функциями, например describe в Jest, добавляются в тот же список.
esModuleInterop позволяет импортировать по умолчанию пакеты CommonJS (import express from "express"). В TypeScript 7 он всегда включён, и значение false это ошибка.
skipLibCheck пропускает проверку типов в файлах объявлений. Он ускоряет сборку и убирает ошибки внутри node_modules, которые вы всё равно не можете исправить, но зато вы не заметите конфликта между типами двух библиотек. Большинство проектов его включают.
Общие настройки через extends
extends загружает другую конфигурацию и позволяет этому файлу переопределить её части:
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["src"]
}
compilerOptions объединяются по каждому параметру, а include, exclude и files из базового файла заменяются, а не объединяются, если этот файл их задаёт. Пути в базовом файле разрешаются относительно базового файла. extends принимает и пакет: проект @tsconfig/bases публикует по одному для каждого окружения, например npm install --save-dev @tsconfig/node24 и затем "extends": "@tsconfig/node24/tsconfig.json".
Чтобы увидеть итоговые настройки после применения всех extends и значений по умолчанию, выполните:
npx tsc --showConfig
Параметры, удалённые в TypeScript 7
TypeScript 6 объявил эти настройки устаревшими, а TypeScript 7 их удалил. Конфигурация, которая всё ещё использует одну из них, завершается ошибкой error TS5108 или TS5102, например Option 'baseUrl' has been removed. Please remove it from your configuration.
| Удалённая настройка | Что использовать вместо |
|---|---|
"target": "es5" | es2015 или новее |
"moduleResolution": "node" (node10) или "classic" | nodenext или bundler |
"module": "amd", "umd", "system", "none" | nodenext, esnext или preserve, а для других форматов бандлер |
baseUrl | Записи paths относительно файла tsconfig |
outFile | Бандлер |
downlevelIteration | Ничего: цели начиная с es2015 поддерживают итерацию нативно |
"esModuleInterop": false, "allowSyntheticDefaultImports": false, "alwaysStrict": false | Удалите строку; эти параметры всегда включены |
Другие изменения этого выпуска, включая новые значения по умолчанию, которых нет в этой таблице, перечислены на странице о TypeScript 7.
Часто задаваемые вопросы
Что такое tsconfig.json?
Это файл конфигурации проекта TypeScript. Его наличие помечает папку как корень проекта, compilerOptions задаёт, как компилятор проверяет и генерирует код, а include, exclude или files указывают, какие файлы входят в проект. Команда tsc без аргументов читает именно его.
Как создать файл tsconfig.json?
Выполните npx tsc --init в папке проекта (с установленным TypeScript). Команда запишет tsconfig.json с рекомендуемыми настройками и комментарием к каждому параметру. Файл можно написать и вручную; {} это корректный tsconfig, в котором действуют все значения по умолчанию.
Какое значение target указать в tsconfig?
Самую старую версию JavaScript, на которой должен работать ваш код. Для современного Node.js безопасно es2022 или новее; по умолчанию TypeScript 7 использует es2025. target определяет, какой новый синтаксис переписывается для старых движков, а также выбирает lib по умолчанию, то есть набор встроенных API, о которых знает проверка типов.
Чем module отличается от moduleResolution?
module определяет, какой модульный код пишет компилятор (ES import/export или CommonJS require) и какие правила модулей действуют. moduleResolution определяет, как путь импорта вроде "./utils.js" или "lodash" ищется на диске. Используйте nodenext для кода, который запускает Node.js, и module: "preserve" (он подразумевает разрешение bundler) для кода, который обрабатывает бандлер.
Можно ли писать комментарии в tsconfig.json?
Да. Компилятор читает его как JSON с комментариями: допускаются комментарии // и /* */ и завершающие запятые, поэтому tsc --init и создаёт файл с кучей закомментированных параметров. Другие инструменты, которые разбирают его как строгий JSON, могут на этом споткнуться.