Содержание
Коротко
Монорепо ломается на цепочках ../../../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.
На практике
- Вынесите общие типы в
packages/typesсexportsи.d.ts. - В корневом
tsconfig.jsonнастройтеbaseUrl,pathsиreferences. - Каждый app:
extends+referencesна types-пакет. - В
package.jsonapps:"@shared/types": "workspace:*". - Собирайте types-пакет первым в pipeline.
- Унифицируйте
moduleResolution: bundlerвезде.
Итог
30 минут на правильный tsconfig экономят часы на импортах и рефакторинге. @shared/types сразу читается как «общий код». Пошаговые конфиги — в оригинале на Dev.to.