When working in a monorepo with multiple applications and packages, it's easy for your TypeScript config files to become redundant, inconsistent, or just plain messy. Fortunately, if you're using Turborepo, you can clean that up with a single, shareable TypeScript config package.
In this blog post, Iβll walk you through how to create a reusable @dtr-cli/typescript-config
-- @dtr-cli is my project package, structure it for multiple project types (backend, frontend, Vite, Next.js etc.), and integrate it across your monorepo like a pro.
β This approach is especially helpful for developers maintaining multiple apps in a monorepo using tools like Turborepo, pnpm workspaces, or Yarn workspaces.
π§© Step-by-Step: Creating the @dtr-cli/typescript-config
Package
1. Create a Package Folder
Inside your packages/
folder, create a new directory called typescript-config
.
mkdir -p packages/typescript-config && cd packages/typescript-config
npm init -y
2. Update the package.json
with a proper name and export map:
{
"name": "@dtr-cli/typescript-config",
"version": "0.0.1",
"description": "Shared Typescript configuration for @dtr-cli",
"license": "ISC",
"author": "Saiful Islam <saiful.islam.rafi.88@gmail.com>",
"exports": {
"./base-tsconfig.json": "./base-tsconfig.json",
"./backend-tsconfig.json": "./backend-tsconfig.json",
"./react-tsconfig.json": "./react-tsconfig.json",
"./vite-node-tsconfig.json": "./vite-node-tsconfig.json"
},
"files": [
"base-tsconfig.json",
"backend-tsconfig.json",
"react-tsconfig.json",
"vite-node-tsconfig.json"
],
"devDependencies": {
"@types/node": "^22.15.15"
}
}
3. Create Base and Extended Configs
Create these four config files inside your package:
base-tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Base",
"compilerOptions": {
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"esModuleInterop": true,
"incremental": false,
"sourceMap": false,
"typeRoots": ["./node_modules/@types"]
}
}
react-tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./base-tsconfig.json",
"display": "React Library",
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx"
}
}
vite-node-tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./base-tsconfig.json",
"display": "Vite Node",
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true
}
}
π Installing the Config Package
To use your shared config package in any app inside your monorepo, add it to the app's package.json
:
"devDependencies": {
"@dtr-cli/typescript-config": "workspace:*"
}
π οΈ How to Use the Configs
Backend App (apps/backend/tsconfig.json
)
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@dtr-cli/typescript-config/backend-tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"typeRoots": ["./node_modules/@types", "./src/types"]
},
"include": ["./src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Vite app (tsconfig.app.json
)
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@dtr-cli/tsconfig-config/react-tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
},
"include": ["src"],
"exclude": ["node_modules", "dist", "test"]
}
Vite app (tsconfig.node.json
)
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@dtr-cli/tsconfig-config/vite-node.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
},
"include": ["vite.config.ts"]
}
Vite app (tsconfig.json
)
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
β Conclusion
By creating a reusable TypeScript config package in Turborepo, you:
- Maintain consistency across all your apps.
- DRY up repeated
tsconfig.json
logic. - Make onboarding and scaling much easier.
If you're managing a modern monorepo setup, especially using TypeScript, Turborepo, and pnpm, this strategy will pay off quickly. Itβs a small step that brings a lot of organization and clarity to your developer experience.
Top comments (0)