ข้ามไปเนื้อหาหลัก

Category: reference

TypeScript Configuration — tsconfig.json Guide

เข้าใจ tsconfig.json ทุก option ที่สำคัญ: strict mode, paths, module resolution, target, lib — ตั้งค่าให้ถูกสำหรับแต่ละ project

· อ่านประมาณ 3 นาที

สารบัญ

tsconfig.json พื้นฐาน

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}

target — JavaScript Version Output

{ "target": "ES2022" }
Targetใช้เมื่อ
ES5รองรับ IE11 (ไม่ค่อยจำเป็นแล้ว)
ES2017Node.js 8+ หรือ browser ที่รองรับ async/await
ES2020Optional chaining ?., nullish coalescing ??
ES2022Top-level await, class fields, Error cause
ESNextล่าสุดเสมอ (ใช้กับ bundler)

module — Module System

{ "module": "ESNext" }  // สำหรับ bundler (Vite, esbuild)
{ "module": "NodeNext" } // สำหรับ Node.js native ESM
{ "module": "CommonJS" } // สำหรับ Node.js เก่า หรือ Jest

moduleResolution

{ "moduleResolution": "bundler" } // Vite, esbuild, Bun
{ "moduleResolution": "NodeNext" } // Node.js ESM
{ "moduleResolution": "node" }     // Node.js CJS (เก่า)

ถ้าใช้ Vite: "moduleResolution": "bundler" ทำงานถูกต้องกับ import.meta, path aliases


strict Mode — เปิดทั้งหมด

{ "strict": true }

เปิดพร้อมกัน:

  • strictNullChecksnull และ undefined ต้อง handle explicit
  • strictFunctionTypes — ตรวจ function parameter contravariance
  • strictBindCallApply — ตรวจ type ของ bind, call, apply
  • strictPropertyInitialization — class property ต้อง initialize ใน constructor
  • noImplicitAny — ห้าม infer any โดยไม่ตั้งใจ
  • noImplicitThis — ห้าม this: any
  • alwaysStrict — เพิ่ม "use strict" ใน output

Options ที่แนะนำเพิ่ม

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,  // arr[0] เป็น T | undefined ไม่ใช่ T
    "exactOptionalPropertyTypes": true, // { a?: string } ไม่รับ { a: undefined }
    "noImplicitReturns": true,          // function ต้อง return ทุก path
    "noFallthroughCasesInSwitch": true, // switch case ต้อมี break/return
    "noImplicitOverride": true,         // method override ต้องใส่ override keyword
    "forceConsistentCasingInFileNames": true
  }
}

Path Aliases

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}
// แทน
import { Button } from '../../components/Button';

// ใช้ได้เลย
import { Button } from '@components/Button';

ถ้าใช้ Vite ต้องตั้งค่า vite.config.ts ด้วย:

import { defineConfig } from 'vite';
import path from 'node:path';

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

Declaration Files

{
  "compilerOptions": {
    "declaration": true,       // สร้าง .d.ts
    "declarationMap": true,    // source map สำหรับ .d.ts
    "emitDeclarationOnly": true // สร้างแค่ .d.ts ไม่ compile JS (ถ้าใช้ bundler)
  }
}

lib — Available Type Definitions

{ "lib": ["ES2022", "DOM", "DOM.Iterable"] }
Libใช้เมื่อ
ES2022JS standard library
DOMBrowser APIs (document, window, fetch)
DOM.IterableNodeList.forEach, HTMLCollection iteration
WebWorkerสำหรับ Web Worker code

Node.js ไม่ต้องใส่ DOM เพราะไม่มี browser API


Config สำหรับแต่ละ Context

Node.js CLI Tool

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "outDir": "dist",
    "sourceMap": true
  }
}

Astro Project

{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["src/*"] }
  }
}

Vite + React

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true
  }
}

Library (npm package)

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": true,
    "strict": true,
    "outDir": "dist"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

Project References (Monorepo)

// root tsconfig.json
{
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/cli" },
    { "path": "./apps/web" }
  ]
}
// packages/core/tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "outDir": "dist"
  }
}

Build:

tsc --build           # build ทุก package
tsc --build --watch   # watch mode
tsc --build --clean   # clean output

skipLibCheck

{ "skipLibCheck": true }

Skip type checking ใน .d.ts files ใน node_modules — เร็วกว่ามาก และหลีกเลี่ยง conflict ระหว่าง packages ที่ใช้ type definitions เวอร์ชันต่างกัน