Урок по треку TypeScript 6 мин

tsconfig и файлы деклараций

strict-флаги, moduleResolution, .d.ts, declare и расширение модулей.

tsconfig.json говорит компилятору, какие файлы брать, насколько строго проверять и что выдавать на выходе. На собесе обычно спрашивают про strict, модули и .d.ts.

strict

"strict": true включает пачку флагов, главные из них:

  • strictNullChecks: null и undefined не входят в остальные типы.
  • noImplicitAny: нельзя оставить параметр без типа, если его не вывести.
  • strictFunctionTypes: параметры функций проверяются контравариантно (для методов, объявленных как методы, остаётся послабление).
  • useUnknownInCatchVariables: catch (e) даёт e: unknown.
  • strictPropertyInitialization: поле класса обязано получить значение в конструкторе.
  • alwaysStrict, strictBindCallApply, noImplicitThis.

Новые флаги семейства strict добавляются в strict в новых версиях, поэтому обновление TypeScript может дать новые ошибки.

Не входят в strict, но полезны: noUncheckedIndexedAccess (доступ по индексу даёт T | undefined), exactOptionalPropertyTypes, noImplicitOverride, noFallthroughCasesInSwitch.

Модули и разрешение импортов

  • module определяет формат выходного кода и правила импорта: esnext, nodenext, preserve.
  • moduleResolution определяет, как искать файлы: bundler для кода под Vite, webpack, Next; nodenext для кода, который запустит Node.js. Старое значение node (node10) устарело.
  • При nodenext в ESM нужно писать расширение в импорте: import { x } from './util.js' (именно .js, даже если файл util.ts).
  • esModuleInterop позволяет import fs from 'fs' для CommonJS-модулей.
  • verbatimModuleSyntax требует import type для импортов, нужных только типам, и не переписывает импорты.

Что выдавать

  • target: до какой версии JS понижать синтаксис. Полифиллы TypeScript не добавляет.
  • lib: какие встроенные типы доступны (dom, es2023). Проект на Node обычно без dom.
  • noEmit: только проверка, сборку делает другой инструмент (Vite, esbuild, SWC). Так устроено большинство фронтенд-проектов.
  • declaration: генерировать .d.ts рядом с JS, нужно для библиотек.
  • isolatedModules: запрещает конструкции, которые нельзя собрать, глядя на один файл. Нужен, когда транспилирует esbuild или SWC.

Пути

paths задаёт алиасы ("@/*": ["./src/*"]). Это знание только для компилятора: сборщик должен понимать тот же алиас, иначе в рантайме импорт не найдётся.

Файлы деклараций

.d.ts содержат только типы, без кода. Откуда берутся:

  1. Поле types в package.json библиотеки.
  2. Пакеты @types/имя из DefinitelyTyped.
  3. Свои декларации в проекте.
// global.d.ts
declare module '*.svg' {
  const src: string;
  export default src;
}

declare global {
  interface Window { ym?: (...args: unknown[]) => void }
}
export {};

declare говорит: значение существует, кода не генерируй. declare global внутри модуля расширяет глобальную область. Расширение модуля (module augmentation) добавляет поля в типы чужой библиотеки:

// в типах Express интерфейс Request объявлен в этом пакете
import 'express-serve-static-core';
declare module 'express-serve-static-core' {
  interface Request { userId?: string }
}

Работает благодаря слиянию интерфейсов. Для Express есть и второй путь: глобальное пространство имён Express (declare global { namespace Express { interface Request { ... } } }).

skipLibCheck: true пропускает проверку всех .d.ts. Ускоряет сборку, но скрывает конфликты в типах зависимостей.

project references

references и composite разбивают монорепо на проекты, которые tsc -b собирает инкрементально и в правильном порядке.

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

  • Ждать, что target: es5 добавит полифилл для Array.prototype.at.
  • Настроить paths и не настроить алиас в сборщике.
  • Забыть export {} в файле с declare global: без импорта или экспорта файл считается скриптом.

Что спросят на собесе

  • Что включает strict и какой флаг самый важный.
  • Чем moduleResolution: bundler отличается от nodenext.
  • Что такое .d.ts и откуда TypeScript берёт типы библиотеки.
  • Как добавить поле в Window или в Request из Express.
  • Зачем isolatedModules и noEmit в проекте на Vite.

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.