在專案開發中,我們常常會在 git commit 前執行 lint 階段檢查,例如搭配 lint-staged 這樣的工具,檢查被修改的檔案是否符合規範。這樣可以避免錯誤代碼混進主分支,非常實用。
但是如果你的專案是 TypeScript,你可能會遇到一個奇怪的問題:
✅ tsc 編譯專案時一切正常
🚫 但在 lint-staged 裡執行時卻報出一堆 tsconfig 裡根本不存在的錯誤
這個問題出在 TypeScript 的檔案解析方式。
當我們平常執行tsc
時,它會從你的根目錄找到tsconfig.json
,然後按照裡面的設定去決定哪些檔案需要檢查、哪些檔案該排除 (exclude
)、哪些檔案該編譯 (include
)。
但在 lint-staged 裡,我們通常是針對「被修改的單獨檔案」去執行,比如這樣設定:
"lint-staged": {
"*.ts": [
"tsc --noEmit"
]
}
這時候lint-staged會將staged files作為參數帶入指令後面,實際運行指令會像這樣:
tsc --noEmit changedFile1.ts changedFile2.ts
因此TypeScript 會用你的單一檔案去解析,無視 tsconfig.json
裡的 include
/exclude
規則,導致出現一些本來不該檢查的檔案錯誤。例如:
.d.ts
檔案找不到定義這時候可以用一個小工具 —— tsc-files。
tsc-files
是一個簡單的命令列工具,它的作用就是「只檢查你指定的檔案,但仍然套用 tsconfig.json 裡的設定」。
用法很簡單,先安裝:
npm install --save-dev tsc-files
然後在 lint-staged
裡把指令換成:
"lint-staged": {
"*.ts": [
"tsc-files --noEmit"
]
}
就這麼簡單。
因為 tsc-files
在底層會先讀取 tsconfig.json
,建立好正確的編譯環境,然後再檢查你傳入的檔案。這樣就不會違反你原本 tsconfig 的 include
/exclude
邏輯,也不會莫名檢查一堆你不想檢查的檔案。
tsc
單檔模式不讀取 tsconfig 的 include
/exclude
tsc-files
,能正確讀取 tsconfig 再檢查單檔