Skip to content

TypeScript Configuration Standardization

This guide explains the standardized TypeScript configuration system implemented across the NexisChat monorepo. The system provides consistent type checking rules while allowing package-specific customizations.

The TypeScript configuration system is built around a hierarchical inheritance model where all packages extend from standardized base configurations. This ensures consistency while maintaining flexibility for different project types.

The configuration system is organized in the packages/typescript-config directory with the following structure:

packages/typescript-config/
├── base.json # Core base configuration
├── node.json # Node.js applications and packages
├── server.json # Server applications (Hono/Express)
├── nextjs.json # Next.js applications
├── astro.json # Astro applications
└── react-library.json # React libraries and components

The base configuration provides core TypeScript settings that work across all project types:

  • Target: ES2022 for modern JavaScript features
  • Module System: ESNext with bundler resolution
  • Strict Mode: Enabled for better type safety
  • Isolated Modules: Enforced for better build performance
  • Skip Lib Check: Enabled to improve compilation speed
  • JSON Module Resolution: Enabled for importing JSON files

Key features:

  • Consistent module resolution strategy
  • Standardized library inclusions
  • Unified strict mode settings
  • Common path resolution patterns
  • Isolated modules enforcement

Used for Node.js server applications like apps/server, apps/evolution-api-lite, and apps/whatsapp-web-server.

Key Features:

  • Extends base configuration
  • Node.js module resolution
  • JSX support for Hono applications
  • Output directory configuration
  • Server-side type definitions

When to use:

  • Backend API servers
  • Node.js applications with JSX
  • Server-side rendering applications

Used for Next.js applications like apps/docs.

Key Features:

  • Next.js plugin integration
  • DOM and DOM.Iterable libraries
  • JSX preserve mode
  • No emit (Next.js handles compilation)
  • Incremental compilation

When to use:

  • Next.js applications
  • React applications with SSR
  • Documentation sites using Next.js

Used for Astro applications like apps/landing.

Key Features:

  • Astro-specific settings
  • Client-side libraries (DOM, DOM.Iterable)
  • ESNext module system
  • JSX preserve mode
  • No emit configuration

When to use:

  • Astro static site generators
  • Multi-framework applications
  • Content-focused websites

Used for Node.js packages and tools like packages/eslint-config.

Key Features:

  • CommonJS module system
  • Node.js module resolution
  • Node.js type definitions
  • Output directory configuration
  • JavaScript support

When to use:

  • Node.js libraries and tools
  • CLI applications
  • Build tools and utilities

Each package in the monorepo extends from the appropriate specialized configuration:

PackageConfigurationRationale
apps/clientreact-library.jsonReact application with bundler
apps/serverserver.jsonHono server with JSX support
apps/docsnextjs.jsonNext.js documentation site
apps/landingastro.jsonAstro static site
apps/evolution-api-litenode.jsonNode.js API server
apps/whatsapp-web-servernode.jsonNode.js WebSocket server
packages/uireact-library.jsonReact component library
packages/eslint-confignode.jsonNode.js configuration package

To use a standardized configuration in your package:

{
"extends": "@repo/typescript-config/server.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

You can override specific compiler options while maintaining inheritance:

{
"extends": "@repo/typescript-config/nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["./src/components/*"],
"@/lib/*": ["./src/lib/*"]
},
"plugins": [{ "name": "next" }, { "name": "@tailwindcss/typography" }]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"]
}

For packages that need additional type definitions:

{
"extends": "@repo/typescript-config/base.json",
"compilerOptions": {
"types": ["node", "jest", "@types/custom-library"]
}
}

The configuration inheritance follows this pattern:

base.json (Core settings)
specialized-config.json (Project-type specific)
package/tsconfig.json (Package-specific overrides)
  • Compiler Options: All base compiler options are inherited
  • Library Inclusions: Base libraries plus specialized additions
  • Strict Mode Settings: Consistent across all packages
  • Module Resolution: Standardized resolution strategy
  • Include/Exclude Patterns: Package-specific file patterns
  • Path Mappings: Internal import aliases
  • Output Directory: Build output location
  • Additional Types: Package-specific type definitions
  • Plugins: Framework-specific plugins

Problem: Cannot find module or type definitions

Solution: Check if the correct base configuration is being used:

{
"extends": "@repo/typescript-config/node.json", // For Node.js packages
"compilerOptions": {
"moduleResolution": "node" // Inherited from node.json
}
}

Problem: JSX syntax not recognized or compiled incorrectly

Solution: Use the appropriate configuration for your JSX needs:

  • React JSX: Use server.json (sets jsx: "react-jsx")
  • Preserve JSX: Use nextjs.json or astro.json (sets jsx: "preserve")

Problem: Types from other packages causing conflicts

Solution: Ensure proper include/exclude patterns:

{
"include": ["src/**/*", "types/**/*"],
"exclude": ["node_modules", "dist", "../**/src"] // Exclude sibling packages
}

Problem: Compiled files in wrong location or format

Solution: Check output configuration:

{
"extends": "@repo/typescript-config/node.json",
"compilerOptions": {
"outDir": "./dist", // Customize output directory
"noEmit": false // Ensure compilation is enabled
}
}

Problem: Cannot find DOM types or Node.js types

Solution: Verify the correct specialized configuration:

// For client-side code
{
"extends": "@repo/typescript-config/nextjs.json", // Includes DOM libraries
}
// For server-side code
{
"extends": "@repo/typescript-config/server.json", // Includes Node.js types
}

Use TypeScript’s --showConfig flag to see the resolved configuration:

Terminal window
npx tsc --showConfig

Ensure your tsconfig.json is valid JSON:

Terminal window
npx tsc --noEmit --project ./tsconfig.json

Run type checking for a specific package:

Terminal window
cd apps/your-package
pnpm typecheck

Verify that the base configuration is being found:

Terminal window
# From package directory
ls -la node_modules/@repo/typescript-config/

The base configuration includes skipLibCheck: true to improve compilation speed. This is generally safe for most projects.

For development, enable incremental compilation:

{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo"
}
}

For large monorepos, consider using TypeScript project references:

{
"references": [{ "path": "../shared-package" }]
}

Only override settings that are absolutely necessary for your package:

// Good: Minimal, necessary overrides
{
"extends": "@repo/typescript-config/nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] }
}
}
// Avoid: Duplicating inherited settings
{
"extends": "@repo/typescript-config/nextjs.json",
"compilerOptions": {
"strict": true, // Already inherited
"skipLibCheck": true, // Already inherited
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] }
}
}

Use consistent include/exclude patterns across similar packages:

{
"include": ["src/**/*", "types/**/*", "*.config.*"],
"exclude": ["node_modules", "dist", "build", ".next"]
}

For packages that need different settings for different environments:

// tsconfig.json (development)
{
"extends": "@repo/typescript-config/server.json",
"compilerOptions": {
"sourceMap": true
}
}
// tsconfig.build.json (production)
{
"extends": "./tsconfig.json",
"compilerOptions": {
"sourceMap": false,
"removeComments": true
},
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
}

Use type-only imports to prevent runtime dependencies:

import type { SomeType } from '@repo/shared-types'
import { someFunction } from '@repo/shared-utils'
  1. Identify Current Configuration: Check your current tsconfig.json
  2. Choose Appropriate Base: Select the right specialized configuration
  3. Update Extends: Change to extend from the standardized config
  4. Remove Redundant Options: Remove settings that are now inherited
  5. Test Type Checking: Verify that everything still works

Before:

{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"outDir": "dist",
"jsx": "react-jsx",
"types": ["node"]
}
}

After:

{
"extends": "@repo/typescript-config/server.json",
"compilerOptions": {
"baseUrl": "."
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

When adding new project types:

  1. Create a new specialized configuration in packages/typescript-config
  2. Extend from base.json
  3. Add project-specific compiler options
  4. Update this documentation
  5. Test with a sample project

When updating the base configuration:

  1. Consider impact on all packages
  2. Test changes across different project types
  3. Update specialized configurations if needed
  4. Communicate changes to the team
  5. Update documentation

The CI system validates TypeScript configurations:

Terminal window
# Run validation across all packages
pnpm ci:validate
# Check specific package
cd apps/your-package && pnpm typecheck

This ensures that all packages maintain consistent and working TypeScript configurations.