← Back to TypeScript Course | Chapter 26: Monorepos and Large Projects | Lesson 1 of 5

Monorepo Setup

A monorepo stores multiple related packages or applications in one repository. TypeScript project configuration can help packages share types and build consistently.
Syntax
typescript
// root package.json
{ "workspaces": ["packages/*"] }

// packages/app/tsconfig.json
{
  "references": [{ "path": "../shared" }]
}

Core Concept

A monorepo keeps multiple related TypeScript packages (a shared library, a backend, a frontend) in one repository with one dependency tree, making cross-package refactors atomic instead of requiring coordinated releases across separate repos.

Example: Core Concept

typescript
// One repo, multiple packages: packages/shared, packages/backend, packages/frontend
console.log("A monorepo makes cross-package refactors atomic, not multi-repo");

Basic Setup

A basic setup uses a workspace tool (npm/yarn/pnpm workspaces or Turborepo) with a root package.json listing workspaces, and each package under packages/* gets its own package.json and tsconfig.json.

Example: Basic Setup

typescript
// root package.json: { "workspaces": ["packages/*"] }
// packages/shared/package.json, packages/shared/tsconfig.json, etc.
console.log("Workspace tooling (npm/yarn/pnpm) links packages together");

Typed Example

TypeScript project references (tsconfig.json's references array) let one package's tsconfig point at another's, so tsc --build compiles them in the correct dependency order and only rebuilds what actually changed.

Example: Typed Example

typescript
// packages/app/tsconfig.json
// { "references": [{ "path": "../shared" }] }
console.log("tsc --build compiles referenced packages in dependency order");

Project Usage

In a real project, a monorepo commonly holds a packages/shared-types package that both a frontend and backend package depend on, keeping request/response types in perfect sync across both sides without copy-pasting.

Example: Project Usage

typescript
// packages/shared-types exports API types used by both frontend and backend
console.log("A shared-types package keeps request/response types in sync");

Best Practices

Use path aliases sparingly and prefer real package references between workspace packages, since aliases can hide a package's actual dependency graph and make tsc --build's incremental ordering unreliable.

Example: Best Practices

typescript
// Prefer real package references over path aliases between workspace packages
console.log("Aliases can hide the real dependency graph tsc --build relies on");
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Publishing a package that depends on another workspace package but forgetting to list it in its dependencies.
  2. Running tsc in each package in the wrong order instead of using project references or a build tool.
  3. Sharing one loose root tsconfig.json for everything, so packages get options they should not.
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.