Skip to main content
Sonamu projects are written in TypeScript, with API and Web each having independent tsconfig.json files. They use configurations optimized for their respective environments.

Project Structure

API and Web are independent TypeScript projects. Their configurations are separate.

API Server Configuration

Base tsconfig.json

api/tsconfig.json
{
  "compilerOptions": {
    /* Basic Options */
    "target": "esnext",
    "module": "esnext",
    "outDir": "dist",
    "sourceMap": true,
    "lib": ["esnext", "dom"],

    /* Strict Type-Checking Options */
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,

    /* Additional Checks */
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "useUnknownInCatchVariables": true,

    /* Module Resolution Options */
    "moduleResolution": "bundler",
    "esModuleInterop": true,

    /* Experimental Options */
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true,
    "noErrorTruncation": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "noUncheckedIndexedAccess": true
  },
  "include": ["src/**/*.ts", "src/**/*.json"],
  "exclude": [
    "node_modules",
    "dist/*",
    "public",
    // "src/**/*.test.ts",  // Test files also type-checked, so commented out
    "**/__mocks__/**",
    "vite.config.ts"
  ]
}

Key Options Explained

{
  "target": "esnext",           // Use latest ECMAScript syntax
  "module": "esnext",            // Output ES modules
  "moduleResolution": "bundler"  // Compatible with Vite/esbuild
}
moduleResolution: “bundler”
  • Uses bundler mode instead of Node.js’s node mode
  • Matches how Vite and esbuild resolve modules
  • Supports package.json’s exports field
Using moduleResolution: "node" may conflict with Vite.

Extended Configuration Files

Sonamu API uses additional tsconfig files for code generation.
api/tsconfig.schemas.json
{
  "extends": "./tsconfig.json",
  "include": ["src/sonamu.generated.ts"],
  "exclude": ["src/**/*.types.ts"]
}
Purpose:
  • Generate sonamu.generated.ts file
  • Generate Entity schema types
  • Convert DB schema → TypeScript types
When Used:
# Automatically used by Sonamu
pnpm sonamu entity:load
api/tsconfig.types.json
{
  "extends": "./tsconfig.json",
  "include": ["src/**/*.types.ts"],
  "references": [{ "path": "./tsconfig.schemas.json" }]
}
Purpose:
  • Generate API response types
  • Define Request/Response types
  • Share types with frontend
When Used:
# Sync types to Web
pnpm sonamu sync:types

Web (React) Configuration

web/tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src", "src/routeTree.gen.ts"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Differences from API

OptionAPIWebReason
moduleResolutionbundlerBundlerVite uses bundler mode
jsx-react-jsxReact 17+ JSX Transform
noEmitfalsetrueVite handles build
isolatedModules-trueRequired by Vite’s esbuild
paths-@/*Absolute path imports
API uses moduleResolution: "bundler" (lowercase), Web uses moduleResolution: "Bundler" (uppercase). Both make Vite resolve modules in bundler mode.

Path Mapping

{
  "paths": {
    "@/*": ["./src/*"]
  }
}
You can import with absolute paths:
// ❌ Relative path
import { Button } from "../../../components/Button";

// ✅ Absolute path
import { Button } from "@/components/Button";
See Path Mapping for details.

Running Type Checks

cd api

# Type check only
pnpm tsc --noEmit

# Watch mode
pnpm tsc --noEmit --watch
During development, --watch mode is recommended for real-time type checking.

Common Troubleshooting

Symptoms:
Cannot find module 'sonamu' or its corresponding type declarations.
Cause:
  • node_modules not installed
  • Incorrect import path
Solution:
# Reinstall dependencies
pnpm install

# Check type definitions
ls node_modules/sonamu/dist/*.d.ts
Symptoms:
Experimental support for decorators is a feature that is subject to change
Cause:
  • experimentalDecorators is disabled
Solution:
{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}
Symptoms:
Cannot use JSX unless the '--jsx' flag is provided.
Cause:
  • jsx option not configured
Solution:
{
  "compilerOptions": {
    "jsx": "react-jsx"
  }
}
Required for React 17+
Symptoms:
Cannot find module '@/components/Button'
Cause:
  • paths configuration missing
  • baseUrl configuration needed
Solution:
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}
Vite configuration also needed:
vite.config.ts
import path from "path";

export default {
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
};

Customization

Additional Library Types

{
  "compilerOptions": {
    "lib": ["esnext", "dom", "dom.iterable", "webworker"]
  }
}

Stricter Checks

{
  "compilerOptions": {
    "noPropertyAccessFromIndexSignature": true,
    "exactOptionalPropertyTypes": true,
    "noUncheckedIndexedAccess": true
  }
}
These options may cause compatibility issues with existing code.

include/exclude Patterns

{
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.json"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.test.ts",
    "**/*.spec.ts",
    "**/__mocks__/**"
  ]
}

Next Steps