TypeScript

Purpose and Scope

This page explains how to use TypeScript in a Turborepo workspace: how to share compiler configuration, how packages consume that configuration, how build and type-check scripts become Turborepo tasks, and how caching changes the developer experience. The first-party TypeScript guide frames the goal as using TypeScript safely across a monorepo while managing the extra setup that comes from having many packages. In practice, that means treating TypeScript configuration as shared workspace infrastructure instead of copying slightly different tsconfig.json files into every app and package.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/index.mdx

The guide assumes a repository shaped like create-turbo or a similar workspace. That matters because the examples use a dedicated package, commonly packages/typescript-config, to publish reusable JSON configuration inside the workspace. Turborepo itself does not replace TypeScript; it coordinates the scripts that run TypeScript and remembers their results when those scripts are deterministic and properly declared. The adjacent tool guides use the same model for Jest, Biome, and Docker: configure the tool normally, then register an appropriate task in turbo.json so Turborepo can parallelize, cache, or intentionally avoid caching it.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/create-turbo-callout.tsx, apps/docs/content/docs/guides/tools/jest.mdx, apps/docs/content/docs/guides/tools/biome.mdx

Relevant Source Files

  • apps/docs/content/docs/guides/tools/typescript.mdx - Primary integration guide for shared tsconfig.json files, package setup, TypeScript builds, and faster workspace type checking.
  • apps/docs/content/docs/guides/tools/biome.mdx - Shows the tool-guide pattern for deciding between root tasks and package tasks, including cache tradeoffs for very fast tools.
  • apps/docs/content/docs/guides/tools/create-turbo-callout.tsx - Defines the shared callout that these guides assume create-turbo or a similarly structured repository.
  • apps/docs/content/docs/guides/tools/docker.mdx - Demonstrates how other tool guides connect Turborepo commands to build and deploy workflows, including TypeScript-adjacent package output concerns.
  • apps/docs/content/docs/guides/tools/index.mdx - Places TypeScript in the broader Tools guide family alongside ESLint, Jest, Vitest, Docker, Biome, and other integrations.
  • apps/docs/content/docs/guides/tools/jest.mdx - Provides the clearest adjacent example of cacheable package tasks versus persistent watch-mode tasks, a distinction that also applies to TypeScript checks.

Core Primitives

The central primitive for TypeScript is tsconfig.json, the TypeScript compiler configuration file. TypeScript supports an extends key, and the Turborepo guide uses that key to share defaults across the workspace. A package such as @repo/typescript-config can expose multiple JSON presets: a base file for common compiler behavior, then specialized presets for environments such as Next.js apps or React libraries. This gives every package a consistent starting point while still allowing the package to choose the preset that matches its runtime, bundler, or framework.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx

The next primitive is the workspace package dependency. The TypeScript guide names the configuration package in package.json as @repo/typescript-config, then installs it into consuming packages as a development dependency. With pnpm, the example uses workspace:*; with yarn, npm, and bun, the guide shows the equivalent dependency style. This is important because the shared configuration is not global state. It is versioned, resolved, and reviewed like any other internal package, so a package’s TypeScript setup is explicit in its own manifest.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx

The final primitive is the Turborepo task. A TypeScript command such as tsc, tsc --noEmit, or a package build script is still declared in package.json; Turborepo’s role begins when that script is registered as a task in turbo.json and run through turbo run. The Jest guide shows the same task contract: package scripts become cacheable tasks, while long-running watch scripts are marked persistent and have cache disabled. For TypeScript, one-time builds and type checks are normally cacheable, while watch-mode compiler processes should be modeled as development tasks rather than cached checks.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/jest.mdx

Sharing TypeScript Configuration

A shared configuration package solves a common monorepo problem: every app needs similar TypeScript defaults, but not every app should maintain its own copy of those defaults. The TypeScript guide starts with packages/typescript-config/base.json, which sets broad compiler behavior such as interoperability, JSON module support, strictness, isolated modules, module detection, and a modern target. The exact options should match the TypeScript version and runtime requirements of the repository, but the pattern is stable: put common policy in a base file, then extend it from more specific configurations.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx

./packages/typescript-config/base.json
{
  "compilerOptions": {
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "es2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "module": "NodeNext"
  }
}

After the base file, create project-specific presets in the same package. The guide calls out nextjs.json and react-library.json as examples of configurations that extend the base and customize behavior for a particular kind of project. This keeps the consuming package’s local tsconfig.json small: it can extend the relevant preset and focus on package-specific details such as includes, excludes, references, or framework-generated files. The repository then has one obvious place to change TypeScript policy, which improves consistency during upgrades and code review.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx

packages/typescript-config/package.json
{
  "name": "@repo/typescript-config"
}

Consuming Configuration in Packages

A consuming package installs both TypeScript and the shared configuration package. In the pnpm example, an app adds @repo/typescript-config with workspace:* and typescript as a dev dependency. The other package-manager examples use equivalent workspace dependency declarations. This placement keeps TypeScript tooling local to the packages that need it, while the shared config remains an internal dependency rather than a copied file. It also makes package boundaries clearer: an app or library declares exactly which shared build policy it relies on.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx

./apps/web/package.json
{
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}

When adding a new app or package, start by choosing the closest shared preset. A Next.js application should extend the Next.js-oriented preset; a reusable React component library should extend the library preset; a plain Node package may extend the base or a server-oriented preset if your repository defines one. This avoids the slow drift that happens when packages copy compiler options and then modify them locally. If a package truly needs different behavior, add that difference intentionally in the package’s local tsconfig.json or introduce a new preset in packages/typescript-config.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/create-turbo-callout.tsx

Task Setup and Caching

Turborepo speeds up TypeScript by running package scripts as tasks and caching successful results. A common setup is to define a type-check or check-types script in each package that runs the TypeScript compiler without emitting files, then register that task in turbo.json. Because type checking is usually deterministic for a known set of source files, dependencies, lockfile state, TypeScript version, and configuration files, it is a good candidate for caching. Subsequent runs can skip unchanged packages and restore prior task results instead of recomputing the full workspace.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/jest.mdx

./packages/ui/package.json
{
  "scripts": {
    "type-check": "tsc --noEmit"
  }
}
./turbo.json
{
  "tasks": {
    "type-check": {}
  }
}

The Jest guide shows a useful distinction for TypeScript workflows: tasks that finish and print output can be cached, but watch-mode tasks are development processes. If you use tsc --watch, create a separate script such as type-check:watch, mark the corresponding Turborepo task as persistent, and disable caching. That keeps the fast feedback loop available during local development without confusing Turborepo’s cache with a process that never exits. The same pattern is used for test watch mode and applies cleanly to long-running TypeScript watchers.

Sources: apps/docs/content/docs/guides/tools/jest.mdx, apps/docs/content/docs/guides/tools/typescript.mdx

./turbo.json
{
  "tasks": {
    "type-check": {},
    "type-check:watch": {
      "cache": false,
      "persistent": true
    }
  }
}

System-to-Code Mapping

Reader taskSource-backed implementation point
Find the official TypeScript integration guidanceapps/docs/content/docs/guides/tools/typescript.mdx defines the page metadata, summary, related guides, and step-by-step TypeScript setup.
Understand the assumed repository shapeapps/docs/content/docs/guides/tools/create-turbo-callout.tsx renders the shared callout that the tool guides assume create-turbo or a similar structure.
Compare TypeScript task design with other toolsapps/docs/content/docs/guides/tools/jest.mdx documents cacheable test tasks and uncached persistent watch tasks.
Decide whether a tool belongs at the root or per packageapps/docs/content/docs/guides/tools/biome.mdx explains root tasks and cache tradeoffs for a very fast workspace-wide tool.
Place the guide in the documentation hierarchyapps/docs/content/docs/guides/tools/index.mdx lists TypeScript among the supported tool integrations.
Connect TypeScript builds to deploy-oriented workflowsapps/docs/content/docs/guides/tools/docker.mdx links the tools section to Docker pruning and optimized build inputs.

Practical Workflow

Start a new repository with create-turbo or mirror its structure in an existing workspace. Add a packages/typescript-config package, give it a package name, and place the base compiler options there. Add specialized presets only when there is a clear consumer category, such as a web app or library package. Then, in each app or package, add the configuration package and TypeScript as development dependencies, extend the appropriate preset, and keep local configuration focused on package-specific file selection or framework requirements.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/create-turbo-callout.tsx

After configuration is shared, make type checking a repeatable task. Add a script to the packages that need type checking, register that task in turbo.json, and run it through turbo run type-check or a root package script that delegates to Turborepo. If the task emits build artifacts, make sure the corresponding Turborepo task configuration describes outputs in the broader task configuration. If the task only validates types with --noEmit, it may not need outputs, but it can still benefit from cached logs and skipped recomputation.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/jest.mdx

For next steps, pair this page with the ESLint and publishing guides. ESLint handles code-quality and environment-variable linting concerns that are separate from the TypeScript compiler. Publishing guidance matters when a package is not merely internal and must produce npm-ready JavaScript and declaration artifacts. Docker guidance is useful when TypeScript builds feed deployment images, because turbo prune --docker narrows Docker inputs to the app and its dependencies. Together, these guides show how TypeScript fits into the larger Turborepo model: configure tools normally, declare tasks clearly, and let Turborepo coordinate work across the workspace.

Sources: apps/docs/content/docs/guides/tools/typescript.mdx, apps/docs/content/docs/guides/tools/docker.mdx, apps/docs/content/docs/guides/tools/index.mdx