上一篇我們已經建立好 React + TypeScript 的新專案環境了,但這還只是開始😌。
這篇會是初始化專案的重要關鍵,我們要來聊聊 Vite 預設專案裡尚未完善的設定,包含 TypeScript 與 ESLint 的 config。由於網路上多數 ESLint 文章仍停留在 9.0 以前的版本,這篇能幫助正在學習的你少走彎路。
本篇重點整理:
tsconfig
設定.eslintrc
vs eslint.config.js
)tsconfig.*
與 eslint.config.js
TypeScript 在網路或歷屆鐵人賽文章中已有大量資源,在這裡我不會贅述太多底層細節,但會在底下附上詳細的參考資料與文章連結,提供給正在學習的各位。
其實 TypeScript 的 預設 config 就已經能夠應付大多數開發需求了。
但在開始調整設定前,我想先補充上一篇沒有提到的工具,同時也是這一次的主題:
這時你會問
我已經有 ESLint 了,怎麼還需要 TypeScript ?
兩者其實角色不同:
function add(a: number, b: number) {
return a + b;
}
add(1, "2"); // ❌ TypeScript 會報錯,字串 "2" 與 型別:number 不一致
const unusedVar = 123; // ⚠️ ESLint 會警告有未使用的變數
function greet(name: string) {
console.log(Name); // ⚠️ ESLint 會警告未定義的變數
}
既然我們已經大致了解了 TypeScript,接下來就來看看一些常見的 config 設定吧!
在建立好專案環境後,通常會看到幾個與 TypeScript 有關的檔案:
tsconfig.json
— 專案通用的基本設定tsconfig.app.json
— 針對前端應用程式程式碼的設定tsconfig.node.json
— 針對 Node.js 環境程式碼的設定 ( 如 vite.config.ts
)vite-env.d.ts
— 用來補充 .env
全域型別下面整理了一些常見的 tsconfig 設定與用途:
"target": "ES2022", // 編譯目標 JS 版本
"module": "ESNext", // 使用 ES 模組
"moduleResolution": "Bundler", // 適合 Vite / ESBuild 的模組解析方式
"strict": true, // 啟用嚴格檢查
"jsx": "react-jsx", // JSX 轉譯,使用 React 17+ JSX runtime
"isolatedModules": true, // 每個檔案可單獨編譯
"noEmit": true, // 只檢查,不輸出檔案
"skipLibCheck": true // 跳過 node_modules 型別檢查,加快編譯速度
在創建新專案後,你應該會發現 eslint.config.js
的檔案。
不過在網路上有許多不同版本的資料,找資料時很容易混淆。這裡我們簡單帶大家了解新舊版本的差異。
ESLint 9.0 以前
.eslintrc
(可能是 .json 或 .js 等格式)來設定規則module.exports = {
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
rules: {
// 自訂規則
},
}
新一代 ESLint (9.x 以上)
eslint.config.js
作為統一入口import { defineConfig } from 'eslint-define-config'
export default defineConfig({
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
rules: {
// 自訂規則
},
})
Prettier 建議直接安裝 VSCode 擴充套件,存檔即可自動整理程式碼,方便又快速
當你在 Vite 專案中開發一段時間後,可能會發現一個問題:
ESLint 沒有即時運作,每次都得手動執行
npm run lint
,甚至要等到 CI/CD 階段才發現一大堆錯誤。
其實這不是 ESLint 壞掉,而是 Vite 預設並沒有幫你把 ESLint 與編輯器完全接上線 😔。
在這裡,我們將這個問題給修復。
安裝 ESLint 的 VSCode 擴充套件
按下 F1
或 ctrl + shift + P
輸入 open settings
,選擇 Open User Settings (JSON)
在 setting.json
原有的程式底下加入以下設定
"eslint.validate": [ // 將以下檔案類型套用 ESLint 檢查
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.useFlatConfig": true // 啟用 ESLint v9 的模式
// false 則為舊式的 .eslintrc
點開專案內的 App.tsx
,你應該能即時看到 ESLint 報錯
在往後開啟新專案後,ESLint 就能即時幫你偵測並提醒錯誤,不需要再手動跑 npm run lint
了。
到這裡,TypeScript 與 ESLint 的基礎設定就大功告成🎉!
接下來我們就能專心在程式功能的開發上,讓環境本身成為默默守護程式品質的後盾🚀
下載開發依賴套件
npm i -D eslint-plugin-react @typescript-eslint/eslint-plugin @typescript-eslint/parser
tsconfig.json
{
"compilerOptions": {
// 編譯 & 模組設定
"module": "ESNext",
"moduleResolution": "Bundler",
"useDefineForClassFields": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"allowImportingTsExtensions": true,
"jsx": "react-jsx",
"noEmit": true,
"skipLibCheck": true,
"isolatedModules": true,
// 嚴格檢查 & linting
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true,
"erasableSyntaxOnly": true
}
}
tsconfig.app.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"types": ["vite/client"],
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
tsconfig.node.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"target": "ES2023",
"lib": ["ES2023"],
"types": ["node"],
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
},
"include": ["vite.config.ts", "scripts", "tools"],
"exclude": ["node_modules", "dist", "src"]
}
eslint.config.js
import js from "@eslint/js";
import globals from "globals";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tsParser from "@typescript-eslint/parser";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import { defineConfig } from "eslint/config";
export default defineConfig([
{
ignores: ["dist/**"],
},
{
files: ["**/*.{ts,tsx}"],
plugins: {
react,
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
"@typescript-eslint": tsPlugin,
},
languageOptions: {
parser: tsParser,
globals: {
...globals.browser,
...globals.node,
"import.meta": "readonly",
},
parserOptions: {
// 使 @typescript-eslint 理解 tsconfig.json 的設定,執行更精確的檢查
project: "./tsconfig.json",
},
},
settings: {
react: { version: "detect" },
},
rules: {
...react.configs.recommended.rules,
...react.configs["jsx-runtime"].rules,
...reactHooks.configs.recommended.rules,
...tsPlugin.configs.recommended.rules,
"react-refresh/only-export-components": "warn",
// 關閉 ESLint 原生規則,改用 TS plugin
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ varsIgnorePattern: "^_", argsIgnorePattern: "^_" },
],
// TypeScript 專案可以關掉 prop-types
"react/prop-types": "off",
},
},
]);
參考資料 & 文章分享:
TypeScript: 語法 & config 設定
ESLint:config 設定