NexisChat Docs

TypeScript Configuration Standardization

Standardized TypeScript configuration system for NexisChat monorepo

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.

Overview

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.

Configuration Hierarchy

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

Base Configuration (base.json)

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

Specialized Configurations

Server Configuration (server.json)

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

Next.js Configuration (nextjs.json)

Used for Next.js applications like apps/docs and apps/subscription.

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

Astro Configuration (astro.json)

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

Node.js Configuration (node.json)

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

Package Configuration Strategy

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/subscriptionnextjs.jsonNext.js application
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

How to Extend Configurations

Basic Extension

To use a standardized configuration in your package:

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

Package-Specific Overrides

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"]
}

Adding Custom Types

For packages that need additional type definitions:

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

Inheritance Hierarchy

The configuration inheritance follows this pattern:

base.json (Core settings)

specialized-config.json (Project-type specific)

package/tsconfig.json (Package-specific overrides)

What Gets Inherited

  • 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

What Can Be Overridden

  • 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

Troubleshooting Guide

Common Issues and Solutions

1. Module Resolution Errors

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
  }
}

2. JSX Compilation Issues

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")

3. Type Checking Isolation Problems

Problem: Types from other packages causing conflicts

Solution: Ensure proper include/exclude patterns:

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

4. Build Output Issues

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
  }
}

5. Library and Types Not Found

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
}

Debugging Configuration Issues

1. Check Configuration Resolution

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

npx tsc --showConfig

2. Validate Configuration Syntax

Ensure your tsconfig.json is valid JSON:

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

3. Test Type Checking

Run type checking for a specific package:

cd apps/your-package
pnpm typecheck

4. Check Inheritance Chain

Verify that the base configuration is being found:

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

Performance Optimization

1. Skip Library Checking

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

2. Incremental Compilation

For development, enable incremental compilation:

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

3. Project References

For large monorepos, consider using TypeScript project references:

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

Best Practices

1. Minimal Overrides

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/*"] }
  }
}

2. Consistent File Patterns

Use consistent include/exclude patterns across similar packages:

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

3. Environment-Specific Configurations

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"]
}

4. Type-Only Imports

Use type-only imports to prevent runtime dependencies:

import type { SomeType } from '@repo/shared-types'
import { someFunction } from '@repo/shared-utils'

Migration Guide

Migrating Existing Packages

  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

Example Migration

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"]
}

Maintenance

Adding New Configurations

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

Updating Base Configuration

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

Configuration Validation

The CI system validates TypeScript configurations:

# 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.