Короткий ответ: путь к типам TypeScript меняют в tsconfig.json, но важно выбрать правильную настройку. Для папок с глобальными .d.ts используют typeRoots, для выбора конкретных пакетов из @types — types, для алиасов импортов — paths, а для включения своих файлов типов в проект часто достаточно include
Самая частая ошибка — прописать typeRoots и случайно отключить обычные типы из node_modules/@types
Если у вас свои глобальные типы
Допустим, структура такая:
src/
index.ts
types/
global/
index.d.ts
tsconfig.json
declare global {
interface Window {
appVersion: string;
}
}
export {};
В tsconfig.json можно просто включить папку:
{
"compilerOptions": {
"strict": true
},
"include": ["src", "types"]
}
Для многих проектов этого достаточно. TypeScript увидит .d.ts файл, потому что он входит в include
Когда нужен typeRoots
typeRoots говорит TypeScript: бери глобальные пакеты типов только из этих папок
Пример:
{
"compilerOptions": {
"typeRoots": ["./types", "./node_modules/@types"]
}
}
Важно: если указать только ./types, TypeScript перестанет автоматически подключать видимые пакеты из node_modules/@types. Поэтому, если вам нужны Node, Jest, Express и другие типы, не забудьте ./node_modules/@types
Используйте typeRoots, когда вы сознательно управляете папками глобальных типов. Если нужно просто добавить один .d.ts, чаще проще include
Когда нужен types
types ограничивает, какие пакеты из @types попадут в глобальную область
Пример:
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
Теперь TypeScript подключит только @types/node и @types/jest, а остальные глобальные типы не попадут в проект
Это полезно, когда в проекте конфликтуют окружения. Например, тестовые типы Jest не должны случайно влиять на production-код
Когда нужен paths
paths не задает путь к глобальным типам. Он задает алиасы импортов
Пример:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@types/*": ["types/*"]
}
}
}
После этого можно писать:
import type { User } from "@/models/User";
Но paths сам по себе не заставляет сборщик понимать алиасы. Vite, webpack, Node.js или Jest тоже нужно настроить, если они выполняют код с такими путями
Пример: типы для API
Если у вас типы лежат отдельно:
src/
api/
client.ts
types/
api.ts
export type ApiUser = {
id: string;
email: string;
};
Импорт:
import type { ApiUser } from "../../types/api";
Или через alias:
import type { ApiUser } from "@types/api";
Но для второго варианта нужен paths и настройка сборщика
Частые ошибки
Первая ошибка — использовать typeRoots, когда нужен paths. Если вы хотите красиво импортировать типы, вам нужен alias, а не глобальная папка типов
Вторая ошибка — указать types: [] и удивиться, что пропали Node-типы. Пустой массив означает: не подключать глобальные @types автоматически
Третья ошибка — положить .d.ts в папку, которая не входит в include. TypeScript ее просто не увидит
Четвертая ошибка — ожидать, что paths изменит runtime. TypeScript понимает alias на этапе проверки, но Node.js или сборщик должны быть настроены отдельно
Самопроверка
Создайте types/global/index.d.ts, добавьте туда Window.appVersion, подключите папку через include и напишите:
window.appVersion = "1.0.0";
Запустите:
npx tsc --noEmit
Если ошибок нет, TypeScript увидел ваши типы. Потом временно уберите types из include и повторите проверку. Ошибка должна вернуться
Что почитать дальше по TypeScript
Если нужен общий маршрут по теме, откройте рубрику TypeScript. Для соседних задач пригодятся эти разборы:
- 10 вопросов по TypeScript и ответы на них
- Any, unknown, never и strict
- App.tsx: что это за файл и как добавить TypeScript в React
- Conditional types в TypeScript: как работает extends



