TypeScript Project References

Project references are a feature provided by TypeScript for organizing large projects, allowing TypeScript projects to be split into smaller parts.

It enables incremental builds, better code organization, and faster compilation.


SVG diagram: How project references work Background Title Project References principle Main project Main project (app) package.json tsconfig.json references: [...] Arrow Referenced project 1 Component library (ui) Button, Modal, Input Referenced project 2 Utility library (utils) formatDate, request Referenced project 3 Type definitions (types) User, API Response Arrow marker

Why project references are needed

As a project grows, a single tsconfig.json can slow down compilation.

Project references allow splitting a project into independent subprojects, each of which can be compiled independently.

This not only improves compilation speed, but also provides a better way to organize code.

Concept:Project references allow one TypeScript project to reference other projects, enabling incremental compilation and better code organization.


Creating a referenced project

First, create the referenced subproject.

packages/utils/tsconfig.json

{
    // Inherit base configuration
    "extends": "../../tsconfig.base.json",

    // Compiler options
    "compilerOptions": {
        // Output directory
        "outDir": "./dist",

        // Declaration file directory
        "declarationDir": "./dist/types",

        // Generate declaration files
        "declaration": true,

        // Generate sourcemap
        "sourceMap": true,

        // Whether it is a library
        "composite": true
    },

    // Included files
    "include": ["src/**/*"],

    // Excluded files
    "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

composite:Set to true to enable the project references feature; this is a required option for referenced projects.


Main project configuration

Configure references in the main project's tsconfig.json.

tsconfig.json (main project)

{
    // Inherit base configuration
    "extends": "./tsconfig.base.json",

    // Compiler options
    "compilerOptions": {
        // Output directory
        "outDir": "./dist",

        // Declaration file directory
        "declarationDir": "./dist/types",

        // Generate declaration files
        "declaration": true,

        // Generate sourcemap
        "sourceMap": true
    },

    // Project references configuration
    "references": [
        // Reference the utils project
        { "path": "./packages/utils" },

        // Reference the ui project
        { "path": "./packages/ui" },

        // Reference the types project
        { "path": "./packages/types" }
    ],

    // Included files
    "include": ["src/**/*"],

    // Dependencies include node modules
    // "files": []
}

references:Each object in the array specifies the path of a referenced project; path is relative to the current project.


Type references

Use types from referenced projects in code.

src/index.ts

// Import utility functions (from utils package)
import { formatDate, formatCurrency } from '@my-utils/format';

// Import components (from ui package)
import { Button, Modal, Input } from '@my-ui/core';

// Import types (from types package)
import { User, ApiResponse } from '@my-types/common';

// Define user data
const user: User = {
    id: 1,
    name: "Alice",
    email: "alice@example.com"
};

// Format date
const dateStr = formatDate(new Date(), "YYYY-MM-DD");
console.log("Date: " + dateStr);

// Format currency
const price = formatCurrency(999);
console.log("Price: " + price);

// Create user interface
const button = new Button({
    text: "Submit",
    variant: "primary"
});

console.log("Application initialized successfully");

Import methods:Exports from referenced projects can be imported directly; TypeScript will automatically resolve the types.


Incremental builds

Project references support incremental builds, compiling only the modified parts.

Build commands

# Build the entire project (including all references)
npm run build

# Build only the main project (do not rebuild dependencies)
npm run build -- --build

# Clean and rebuild
npm run clean
npm run build

# Incremental build (recommended)
# After modifying a package, only recompile that package and packages that depend on it
npx tsc -b packages/utils
npx tsc -b packages/ui
npx tsc -b .

Incremental build:When using the -b (build) option, TypeScript automatically detects which projects need to be recompiled.


Notes

  • composite option:Referenced projects must set composite: true
  • Output directory:Each project needs an independent output directory
  • Declaration files:Referenced projects need to generate declaration files
  • Build order:Dependent projects need to be built first

Best practices:Split common code into independent packages and manage them with project references to improve compilation efficiency.


Summary

Project references are a core feature of TypeScript for managing large projects.

  • references:Configure the project reference relationships
  • composite:Enable project references
  • Incremental build:Compile only the modified parts
  • Code organization:Split into independent modules

Suggestion:In large projects, use project references to organize code and improve development efficiency.

Other extensions