Repo
Docs
TypeScript

TypeScript in a monorepo

You can use TypeScript in a monorepo in one of two ways - as a linter, or as a build tool.

In this section, we'll discuss TypeScript's role as a linter. This is when you prevent TypeScript emitting files (with noEmit (opens in a new tab)) and instead use it only to check your source code's types.

Sharing tsconfig.json

We can share TypeScript config files across our repository with a clever solution. We can put our base tsconfig.json files in a single workspace, and extend them from the tsconfig.json files in our apps.

Let's imagine a workspace like this:

apps
β”œβ”€ docs
β”‚  β”œβ”€ package.json
β”‚  β”œβ”€ tsconfig.json
β”œβ”€ web
β”‚  β”œβ”€ package.json
β”‚  β”œβ”€ tsconfig.json
packages
β”œβ”€ tsconfig
β”‚  β”œβ”€ base.json
β”‚  β”œβ”€ nextjs.json
β”‚  β”œβ”€ package.json
β”‚  β”œβ”€ react-library.json

Our tsconfig package

Inside packages/tsconfig, we have a few json files which represent different ways you might want to configure TypeScript. They each look like this:

packages/tsconfig/base.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Default",
  "compilerOptions": {
    "composite": false,
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "inlineSources": false,
    "isolatedModules": true,
    "moduleResolution": "node",
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "preserveWatchOutput": true,
    "skipLibCheck": true,
    "strict": true
  },
  "exclude": ["node_modules"]
}

Inside package.json, we simply name our package:

packages/tsconfig/package.json
{
  "name": "tsconfig"
}

The other json files in the repository can be accessed via a simple import:

import baseJson from "tsconfig/base.json";
import nextjsJson from "tsconfig/nextjs.json";
import reactLibraryJson from "tsconfig/react-library.json";

This lets us export different config settings for different types of projects.

How to use the tsconfig package

Each app/package which uses our shared tsconfig must first specify it as a dependency:

apps/web/package.json
{
  "dependencies": {
    "tsconfig": "*"
  }
}

Then, they can extend it inside their own tsconfig.json:

apps/web/tsconfig.json
{
  // We extend it from here!
  "extends": "tsconfig/nextjs.json",
 
  // You can specify your own include/exclude
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}

Summary

This setup ships by default when you create a new monorepo with npx create-turbo@latest. You can also look at our basic example (opens in a new tab) to see a working version.

Running tasks

We recommend following the setup in the basics section.