TypeScript 設定檔詳解 (tsconfig.json)

tsconfig.json 是 TypeScript 專案的設定檔,用來指定編譯選項和專案結構。這篇文章會詳細介紹常用的設定選項。

建立設定檔

使用 TypeScript 編譯器建立預設設定檔:

tsc --init

這會產生一個包含註解說明的 tsconfig.json 檔案。

基本結構

{
  "compilerOptions": {
    // 編譯選項
  },
  "include": [
    // 要編譯的檔案
  ],
  "exclude": [
    // 要排除的檔案
  ],
  "files": [
    // 明確指定的檔案
  ]
}

檔案包含設定

include

指定要包含的檔案或目錄:

{
  "include": ["src/**/*", "types/**/*"]
}

支援 glob 模式:

  • *:匹配任意字元(不包含目錄分隔符)
  • **:匹配任意深度的目錄
  • ?:匹配單一字元

exclude

排除不需要編譯的檔案:

{
  "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}

預設會排除 node_modulesbower_componentsjspm_packagesoutDir

files

明確指定要編譯的檔案(不支援 glob):

{
  "files": ["src/index.ts", "src/utils.ts"]
}

編譯目標設定

target

指定編譯後的 JavaScript 版本:

{
  "compilerOptions": {
    "target": "ES2020"
  }
}

常見值:

  • ES5:較舊的瀏覽器相容
  • ES6/ES2015:支援 class、arrow function 等
  • ES2020:支援 optional chaining、nullish coalescing
  • ESNext:最新的 ECMAScript 版本

module

指定模組系統:

{
  "compilerOptions": {
    "module": "ESNext"
  }
}

常見值:

  • CommonJS:Node.js 預設
  • ES6/ES2015/ES2020:ES 模組
  • ESNext:最新的模組系統
  • AMDUMDSystem:其他模組系統

lib

指定要包含的內建型別定義:

{
  "compilerOptions": {
    "lib": ["ES2020", "DOM", "DOM.Iterable"]
  }
}

常見值:

  • ES5ES6ES2020 等:JavaScript 內建型別
  • DOM:瀏覽器 DOM API
  • WebWorker:Web Worker API

輸出設定

outDir

指定編譯後檔案的輸出目錄:

{
  "compilerOptions": {
    "outDir": "./dist"
  }
}

rootDir

指定原始碼的根目錄:

{
  "compilerOptions": {
    "rootDir": "./src"
  }
}

outFile

將所有輸出合併為單一檔案(僅限 AMD 或 System 模組):

{
  "compilerOptions": {
    "outFile": "./dist/bundle.js"
  }
}

declaration

產生 .d.ts 型別宣告檔案:

{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./dist/types"
  }
}

sourceMap

產生 source map 檔案,方便除錯:

{
  "compilerOptions": {
    "sourceMap": true
  }
}

嚴格模式設定

strict

啟用所有嚴格檢查:

{
  "compilerOptions": {
    "strict": true
  }
}

這等同於啟用以下所有選項:

{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true
  }
}

noImplicitAny

禁止隱式 any 型別:

// noImplicitAny: true
function greet(name) {
  // 錯誤:參數 'name' 隱式具有 'any' 型別
  console.log(name);
}

// 需要明確標註型別
function greet(name: string) {
  console.log(name);
}

strictNullChecks

嚴格的 null 和 undefined 檢查:

// strictNullChecks: true
let name: string = null; // 錯誤

let name: string | null = null; // OK

noImplicitReturns

確保函式所有路徑都有回傳值:

// noImplicitReturns: true
function getValue(condition: boolean): number {
  if (condition) {
    return 1;
  }
  // 錯誤:不是所有程式碼路徑都回傳值
}

noUnusedLocals

檢查未使用的區域變數:

// noUnusedLocals: true
function example() {
  const unused = 'hello'; // 錯誤:'unused' 已宣告但從未使用
}

noUnusedParameters

檢查未使用的函式參數:

// noUnusedParameters: true
function greet(name: string, unused: number) {
  // 錯誤:'unused' 未使用
  console.log(name);
}

// 使用 _ 前綴可以忽略
function greet(name: string, _unused: number) {
  console.log(name);
}

模組解析設定

moduleResolution

指定模組解析策略:

{
  "compilerOptions": {
    "moduleResolution": "node"
  }
}

值:

  • node:Node.js 風格解析
  • bundler:適用於打包工具(TypeScript 5.0+)
  • classic:舊版 TypeScript 解析

baseUrl

設定模組解析的基礎路徑:

{
  "compilerOptions": {
    "baseUrl": "./src"
  }
}

paths

設定路徑別名:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@/*": ["./*"],
      "@components/*": ["./components/*"],
      "@utils/*": ["./utils/*"]
    }
  }
}

使用:

import { Button } from '@components/Button';
import { formatDate } from '@utils/date';

typeRoots

指定型別定義的搜尋目錄:

{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./types"]
  }
}

types

只包含指定的型別套件:

{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

JavaScript 互通設定

allowJs

允許編譯 JavaScript 檔案:

{
  "compilerOptions": {
    "allowJs": true
  }
}

checkJs

對 JavaScript 檔案進行型別檢查:

{
  "compilerOptions": {
    "checkJs": true
  }
}

esModuleInterop

啟用 ES 模組和 CommonJS 的互通:

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

這允許:

// 可以使用預設匯入 CommonJS 模組
import express from 'express';
// 而不是
import * as express from 'express';

allowSyntheticDefaultImports

允許從沒有預設匯出的模組使用預設匯入:

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true
  }
}

JSX 設定

jsx

指定 JSX 的編譯方式:

{
  "compilerOptions": {
    "jsx": "react-jsx"
  }
}

值:

  • preserve:保留 JSX,由其他工具處理
  • react:轉換為 React.createElement
  • react-jsx:轉換為 _jsx(React 17+)
  • react-native:保留 JSX

其他常用設定

skipLibCheck

跳過型別宣告檔案的檢查:

{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

可以加快編譯速度,但可能忽略某些型別錯誤。

forceConsistentCasingInFileNames

強制檔案名稱大小寫一致:

{
  "compilerOptions": {
    "forceConsistentCasingInFileNames": true
  }
}

resolveJsonModule

允許匯入 JSON 檔案:

{
  "compilerOptions": {
    "resolveJsonModule": true
  }
}

isolatedModules

確保每個檔案可以獨立編譯:

{
  "compilerOptions": {
    "isolatedModules": true
  }
}

這在使用 Babel 或其他轉譯器時很重要。

常見設定範例

React 專案

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Node.js 專案

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

函式庫專案

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

繼承設定

使用 extends 繼承其他設定檔:

// tsconfig.base.json
{
    "compilerOptions": {
        "strict": true,
        "esModuleInterop": true
    }
}

// tsconfig.json
{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "outDir": "./dist"
    },
    "include": ["src"]
}

專案參考 (Project References)

用於大型 monorepo 專案:

// tsconfig.json
{
  "references": [
    { "path": "./packages/common" },
    { "path": "./packages/frontend" },
    { "path": "./packages/backend" }
  ]
}