跳至主要內容
Skip to content

Node.js + TypeScript 環境設定

本篇將帶你從零開始配置 Node.js + TypeScript 開發環境,包含多種執行方式和最佳實踐。


一、 初始化專案

1.1 建立專案

bash
mkdir my-node-app
cd my-node-app
npm init -y

1.2 安裝 TypeScript

bash
npm install -D typescript @types/node

1.3 初始化 tsconfig.json

bash
npx tsc --init

二、 tsconfig.json 配置

2.1 Node.js 推薦配置

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

2.2 重要選項說明

選項說明
target編譯目標,Node 18+ 用 ES2022
module模組系統,NodeNext 支援 ESM
moduleResolution模組解析策略
outDir輸出目錄
rootDir原始碼目錄
strict嚴格模式
esModuleInteropCommonJS 相容
declaration產生 .d.ts 檔案

三、 執行方式

3.1 編譯後執行

bash
# 編譯
npx tsc

# 執行
node dist/index.js

3.2 使用 ts-node

bash
npm install -D ts-node

# 執行
npx ts-node src/index.ts

3.3 使用 tsx(推薦)

bash
npm install -D tsx

# 執行
npx tsx src/index.ts

# 監聽模式
npx tsx watch src/index.ts

> `tsx` 比 `ts-node` 更快,支援 ESM,推薦使用。


四、 開發腳本

4.1 package.json 腳本

json
{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "lint": "eslint src --ext .ts",
    "type-check": "tsc --noEmit"
  }
}

4.2 使用 nodemon

bash
npm install -D nodemon
json
{
  "scripts": {
    "dev": "nodemon --exec tsx src/index.ts"
  }
}

nodemon.json:

json
{
  "watch": ["src"],
  "ext": "ts,json",
  "ignore": ["dist"],
  "exec": "tsx src/index.ts"
}

五、 ESM 與 CommonJS

5.1 使用 ESM

package.json:

json
{
  "type": "module"
}

tsconfig.json:

json
{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext"
  }
}
typescript
// ESM 語法
import { readFile } from 'fs/promises';
import path from 'path';

const content = await readFile(path.join(process.cwd(), 'data.json'), 'utf-8');

5.2 使用 CommonJS

package.json(不設定 type 或設為 commonjs):

json
{
  "type": "commonjs"
}

tsconfig.json:

json
{
  "compilerOptions": {
    "module": "CommonJS",
    "moduleResolution": "Node"
  }
}
typescript
// CommonJS 語法
import fs from 'fs';
import path from 'path';

const content = fs.readFileSync(path.join(__dirname, 'data.json'), 'utf-8');

六、 路徑別名

6.1 設定 tsconfig.json

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

6.2 使用 tsconfig-paths

bash
npm install -D tsconfig-paths
json
{
  "scripts": {
    "dev": "ts-node -r tsconfig-paths/register src/index.ts"
  }
}

6.3 使用 tsx(自動支援)

bash
npx tsx src/index.ts  # 自動解析路徑別名

七、 環境變數

7.1 使用 dotenv

bash
npm install dotenv
npm install -D @types/node
typescript
// src/index.ts
import dotenv from 'dotenv';

dotenv.config();

const port = process.env.PORT ?? 3000;
const dbUrl = process.env.DATABASE_URL;

console.log(`Server running on port ${port}`);

7.2 類型安全的環境變數

typescript
// src/env.ts
import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z
    .enum(['development', 'production', 'test'])
    .default('development'),
  PORT: z.string().transform(Number).default('3000'),
  DATABASE_URL: z.string().url(),
});

const parsed = envSchema.safeParse(process.env);

if (!parsed.success) {
  console.error('Invalid environment variables:', parsed.error.flatten());
  process.exit(1);
}

export const env = parsed.data;
typescript
// 使用
import { env } from './env';

console.log(env.PORT); // number
console.log(env.NODE_ENV); // 'development' | 'production' | 'test'
console.log(env.DATABASE_URL); // string

八、 專案結構

8.1 推薦結構

my-node-app/
├── src/
│   ├── config/
│   │   └── env.ts
│   ├── controllers/
│   ├── middleware/
│   ├── routes/
│   ├── services/
│   ├── types/
│   │   └── index.ts
│   ├── utils/
│   └── index.ts
├── dist/
├── .env
├── .env.example
├── .gitignore
├── package.json
├── tsconfig.json
└── nodemon.json

8.2 類型定義

typescript
// src/types/index.ts
export interface User {
  id: number;
  name: string;
  email: string;
}

export interface ApiResponse<T> {
  success: boolean;
  data: T;
  message?: string;
}

九、 ESLint 配置

9.1 安裝

bash
npm install -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

9.2 .eslintrc.cjs

javascript
module.exports = {
  root: true,
  env: {
    node: true,
    es2022: true,
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
  ],
  rules: {
    '@typescript-eslint/no-unused-vars': 'warn',
    '@typescript-eslint/explicit-function-return-type': 'off',
    semi: ['error', 'never'],
    quotes: ['error', 'single'],
  },
};

總結

工具用途推薦
tsc編譯生產環境
ts-node直接執行一般
tsx快速執行推薦
nodemon監聽變更搭配使用
設定ESMCommonJS
package.json typemodulecommonjs
tsconfig moduleNodeNextCommonJS
匯入語法import fromimport from

> **推薦配置**:

  • 使用 ESM("type": "module"
  • 開發用 tsx watch
  • 生產用 tsc 編譯後執行

進階挑戰

  1. 設定一個支援熱重載的開發環境
  2. 配置 Jest 測試框架 + TypeScript
  3. 建立一個 CLI(命令列工具)應用

延伸閱讀與資源