Установка и tsconfig

Настройка TypeScript-проекта через npm и конфигурацию tsconfig.json для управления компиляцией.

Зачем нужно

  • Без установки TypeScript нельзя компилировать .ts файлы
  • tsconfig.json определяет правила компиляции, строгость проверок и структуру проекта
  • Правильная конфигурация — фундамент надёжного TS-проекта

Где используется

  • Любой TypeScript-проект начинается с npm init + npm install typescript
  • tsconfig.json лежит в корне каждого TS-проекта
  • Монорепозитории используют project references для связи нескольких tsconfig.json

Предпосылки

  • Установленный Node.js (v16+) и npm
  • Базовое понимание npm и package.json
  • Знание Что такое TypeScript

Установка TypeScript

Глобальная установка (для экспериментов)

npm install -g typescript

# Проверка версии
tsc --version
# Version 5.x.x

Локальная установка (рекомендуется для проектов)

# Создаём проект
mkdir my-ts-project && cd my-ts-project
npm init -y

# Устанавливаем TypeScript как dev-зависимость
npm install --save-dev typescript

# Запускаем через npx
npx tsc --version

Установка с полезными дополнениями

# TypeScript + типы для Node.js + ts-node для запуска без компиляции
npm install --save-dev typescript @types/node ts-node

# Или с tsx (более быстрая альтернатива ts-node)
npm install --save-dev typescript @types/node tsx

Инициализация tsconfig.json

# Создаёт tsconfig.json с комментариями по всем опциям
npx tsc --init

Структура tsconfig.json

{
  // Опции компилятора
  "compilerOptions": {
    // ... все настройки компиляции
  },

  // Какие файлы включить
  "include": ["src/**/*"],

  // Какие файлы исключить
  "exclude": ["node_modules", "dist", "**/*.test.ts"],

  // Конкретные файлы (вместо include)
  "files": ["src/index.ts"],

  // Ссылки на другие tsconfig (для монорепо)
  "references": [{ "path": "../shared" }],

  // Наследование от другого конфига
  "extends": "@tsconfig/node20/tsconfig.json"
}

Ключевые опции компилятора

target — версия JavaScript на выходе

{
  "compilerOptions": {
    // В какую версию JS компилировать
    "target": "ES2022"
    // Варианты: ES3, ES5, ES6/ES2015, ES2016...ES2023, ESNext
  }
}
Значение Когда использовать
ES5 Поддержка старых браузеров
ES2020 Современные браузеры
ES2022 Node.js 18+
ESNext Всегда последняя версия

module — система модулей

{
  "compilerOptions": {
    "module": "ESNext"
    // Варианты: CommonJS, ES6/ES2015, ES2020, ES2022, ESNext, Node16, NodeNext
  }
}
Значение Когда использовать
CommonJS Старый Node.js (require/module.exports)
ESNext Бандлеры (Vite, webpack, esbuild)
Node16 / NodeNext Node.js 16+ с ESM

strict — строгая проверка типов

{
  "compilerOptions": {
    // Включает ВСЕ strict-опции разом
    "strict": true

    // Что входит в strict:
    // "strictNullChecks": true        — null/undefined отделены от других типов
    // "strictFunctionTypes": true     — строгая проверка типов функций
    // "strictBindCallApply": true     — проверка bind/call/apply
    // "strictPropertyInitialization": true — свойства классов инициализированы
    // "noImplicitAny": true           — запрет неявного any
    // "noImplicitThis": true          — запрет неявного this
    // "alwaysStrict": true            — "use strict" в каждом файле
    // "useUnknownInCatchVariables": true — catch(e) → e: unknown
  }
}

outDir и rootDir — структура папок

{
  "compilerOptions": {
    // Откуда брать исходники
    "rootDir": "./src",

    // Куда складывать скомпилированные файлы
    "outDir": "./dist"
  }
}
my-project/
├── src/              ← rootDir
│   ├── index.ts
│   └── utils/
│       └── helpers.ts
├── dist/             ← outDir (создаётся автоматически)
│   ├── index.js
│   └── utils/
│       └── helpers.js
└── tsconfig.json

esModuleInterop — совместимость импортов

{
  "compilerOptions": {
    // Позволяет import x from "module" для CommonJS-модулей
    "esModuleInterop": true
  }
}
// Без esModuleInterop — нужен такой синтаксис:
import * as express from "express";

// С esModuleInterop — можно писать нормально:
import express from "express";

jsx — поддержка JSX/TSX

{
  "compilerOptions": {
    "jsx": "react-jsx"
    // Варианты:
    // "react"      — React.createElement (старый React)
    // "react-jsx"  — автоматический JSX runtime (React 17+)
    // "react-jsxdev" — dev-версия react-jsx
    // "preserve"   — не трансформировать (для Babel/другого инструмента)
  }
}

Другие важные опции

{
  "compilerOptions": {
    // Разрешение модулей
    "moduleResolution": "bundler",  // Для бандлеров
    // "moduleResolution": "node16", // Для Node.js

    // Путевые алиасы
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@utils/*": ["src/utils/*"]
    },

    // Декораторы (для NestJS, Angular)
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

    // Source maps для отладки
    "sourceMap": true,

    // Генерация .d.ts файлов
    "declaration": true,
    "declarationMap": true,

    // Инкрементальная компиляция
    "incremental": true,

    // Запретить неиспользуемые переменные
    "noUnusedLocals": true,
    "noUnusedParameters": true,

    // Проверять switch/case на полноту
    "noFallthroughCasesInSwitch": true,

    // Разрешить импорт .json() файлов
    "resolveJsonModule": true,

    // Каждый файл — отдельный модуль
    "isolatedModules": true,

    // Не генерировать JS (только проверка типов)
    "noEmit": true,

    // Пропустить проверку типов .d.ts файлов (ускоряет компиляцию)
    "skipLibCheck": true
  }
}

Готовые конфигурации для разных сценариев

Frontend (React + Vite)

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

Backend (Node.js)

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "sourceMap": true,
    "incremental": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

Библиотека (npm-пакет)

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

Project References (монорепо)

// tsconfig.json (корневой)
{
  "references": [
    { "path": "./packages/shared" },
    { "path": "./packages/client" },
    { "path": "./packages/server" }
  ],
  "files":  // корневой конфиг сам ничего не компилирует
}

// packages/shared/tsconfig.json
{
  "compilerOptions": {
    "composite": true,  // обязательно для references
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true
  },
  "include": ["src"]
}

// packages/client/tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "references": [
    { "path": "../shared" }  // зависит от shared
  ],
  "include": ["src"]
}
# Собрать все проекты с учётом зависимостей
npx tsc --build
# или сокращённо
npx tsc -b

Наследование конфигураций (extends)

# Установка готовых базовых конфигов
npm install --save-dev @tsconfig/node20
npm install --save-dev @tsconfig/strictest
// tsconfig.json
{
  "extends": "@tsconfig/node20/tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"]
}

Частые ошибки

  1. Не указан include или files — компилятор подхватит все .ts в проекте, включая node_modules
  2. rootDir не совпадает с реальной структурой — пути в dist будут неожиданными
  3. Забыт esModuleInterop — импорты CommonJS-модулей ломаются
  4. strict: false в новом проекте — всегда начинайте со strict: true
  5. Не установлены @types/* — TypeScript не знает типы сторонних библиотек
# Типичная ошибка: модуль не найден
# Could not find a declaration file for module 'express'

# Решение:
npm install --save-dev @types/express
  1. Конфликт module и moduleResolution — используйте совместимые пары:
    • "module": "CommonJS" + "moduleResolution": "node"
    • "module": "Node16" + "moduleResolution": "Node16"
    • "module": "ESNext" + "moduleResolution": "bundler"

Практика

  1. Создайте новый проект:
    mkdir ts-practice && cd ts-practice
    npm init -y
    npm install --save-dev typescript @types/node
    npx tsc --init
    
  2. Настройте tsconfig.json для Node.js проекта
  3. Создайте src/index.ts с простой функцией
  4. Скомпилируйте: npx tsc
  5. Проверьте вывод в dist/
  6. Попробуйте изменить target на ES5 и сравните вывод

Связанные темы

Ресурсы