← Все статьи

Path aliases в TypeScript-монорепо: Astro, React и общие типы

baseUrl, paths и project references: @shared/types вместо ../../../ и тихие падения сборки без workspace:*.

Содержание

Коротко

Монорепо ломается на цепочках ../../../packages/types. Автор CitizenApp описывает настройку TypeScript path aliases для Astro, React 19 и общего пакета @shared/types — читаемые импорты и безопасный рефакторинг.

Что произошло

Три подхода к общим типам: относительные пути (хрупко), публикация в npm (избыточно для внутреннего кода), path aliases (золотая середина). Структура: packages/types/, приложения в apps/web (Astro), apps/dashboard (React), корневой tsconfig.json.

Пакет типов компилируется отдельно с declaration: true, moduleResolution: bundler. В package.json поле exports указывает на ./dist/index.d.ts — без двусмысленности для потребителей.

Корневой конфиг задаёт baseUrl: "." и paths: { "@shared/*": ["packages/*/src"] }. Project references связывают workspaces как отдельные единицы компиляции — быстрее инкрементальные сборки, меньше циклических зависимостей. Каждое приложение extends корень и добавляет references на packages/types.

Импорт становится import { User } from '@shared/types' — IDE автодополняет, перенос файла обновляет ссылки. FastAPI aliases не понимает; типы генерируют в Python через datamodel-code-generator, источник правды остаётся в TS.

Почему это важно

Без workspace:* в зависимостях приложений сборка падает с «cannot find module» — иногда тихо на CI. Порядок сборки: сначала packages/types, потом apps — в pnpm / Turborepo это явно.

Ещё грабля: разный moduleResolution локально (nodeNext) и на Vercel (bundler) — paths резолвятся по-разному. Для современных монорепо автор рекомендует bundler.

На практике

  1. Вынесите общие типы в packages/types с exports и .d.ts.
  2. В корневом tsconfig.json настройте baseUrl, paths и references.
  3. Каждый app: extends + references на types-пакет.
  4. В package.json apps: "@shared/types": "workspace:*".
  5. Собирайте types-пакет первым в pipeline.
  6. Унифицируйте moduleResolution: bundler везде.

Итог

30 минут на правильный tsconfig экономят часы на импортах и рефакторинге. @shared/types сразу читается как «общий код». Пошаговые конфиги — в оригинале на Dev.to.