具代表性的面試主題

程式設計面試:如何評估 Node.js 內建 TypeScript 型別擦除?

程式題中等
Offer.cc 編輯團隊發佈 更新

題幹

團隊想在 Node.js 中直接執行 TypeScript,減少建置步驟。你會如何判斷內建 type stripping 是否適合生產,並規劃從 tsx 或編譯產物的遷移?

題幹與適用場景

一個 Node.js 服務目前用 TypeScript 編譯成 JavaScript,再由容器啟動;團隊希望直接執行 .ts 檔案以縮短腳本與開發工具鏈。請說明內建 type stripping 的工作方式、支援邊界、模組解析、設定限制、測試與生產發布策略。

面試官考察點

  • 是否知道 Node.js 只移除型別標註,不做型別檢查,也不產生執行時程式碼。
  • 是否能識別列舉、含執行時程式碼的 namespace、參數屬性、裝飾器等不可擦除語法。
  • 是否理解 Node.js 不讀取 tsconfig.json,路徑別名與目標轉換不會自動生效。
  • 是否能區分開發腳本、編譯產物、依賴套件與生產服務的風險邊界。

回答前需要釐清的問題

  1. 目標是開發腳本、CLI、測試,還是長期執行的生產服務?
  2. 程式碼是否使用列舉、裝飾器、參數屬性、namespace 或路徑別名?
  3. 目前模組模式、Node 版本、TypeScript 版本與發布映像檔是否可統一?
  4. 團隊是否需要完整型別檢查、原始碼轉換、source map 或舊 Node 版本支援?

30 秒回答框架

我會把內建能力定位為輕量執行器:它把可擦除的型別語法替換為空白,不檢查型別,也不為列舉或裝飾器產生 JavaScript。先掃描程式碼並固定 Node 版本;使用 import type、明確副檔名與 module 規則,避免依賴 tsconfig 路徑別名。需要完整 TypeScript 語義的服務繼續使用編譯器或 tsx,內建模式先用於腳本與小型工具。CI 同時執行型別檢查、執行時測試與建置產物檢查,再按故障率與啟動時間決定範圍。

分步驟深入解答

1. 解釋型別擦除模型

Node.js 會把型別標註替換為空白,因此堆疊行號通常不需要 source map;它不會檢查型別,也不轉換需要產生 JavaScript 的語法。列舉、含執行時程式碼的 namespace、參數屬性與裝飾器會觸發不支援錯誤。只有可擦除語法的檔案才適合直接執行。

2. 固定模組與匯入規則

Node.js 同時支援 CommonJS 與 ES module 的 TypeScript 檔案,實際模式由套件設定、副檔名與執行方式決定。型別匯入必須使用 import type,否則擦除後仍會被當作值匯入而在執行時失敗。相對路徑應寫出可解析的副檔名,並透過 package.jsonimports 等機制取代無法由 Node 轉換的路徑別名。

3. 處理 tsconfig 與依賴邊界

內建執行器忽略 tsconfig.json,不會執行 target 降級、paths 映射或其他編譯轉換。Node.js 也拒絕處理 node_modules 目錄下的 TypeScript 檔案,以避免依賴套件把原始碼執行當作發布契約。需要轉換、裝飾器或第三方 TypeScript 依賴時,繼續使用完整編譯器或執行時工具。

4. 設計遷移驗證與回滾

先在 Node 版本矩陣中執行 lint、型別檢查、單元測試、整合測試與啟動探針,再比較編譯模式與擦除模式的行為、啟動時間與錯誤日誌。鎖定 Node 版本;v25.2 與 v24.12 起 type stripping 穩定,v26 移除實驗性轉換開關。生產失敗時切回編譯產物,而不是臨時開啟不支援的語法轉換。

高品質示範回答

我會把內建 type stripping 當作輕量的 TypeScript 執行路徑,而非完整編譯器。先盤點程式碼是否使用列舉、裝飾器、參數屬性、執行時 namespace、paths 別名或依賴套件中的 TypeScript;這些能力需要轉換或型別檢查,繼續保留編譯器或 tsx。可遷移程式碼使用 import type、穩定的模組模式與可解析相對路徑,型別檢查仍由 tsc --noEmit 完成。Node.js 不讀取 tsconfig,因此建置腳本要明確設定 package.json 與匯入映射。先在開發腳本與 CLI 灰度,CI 比較啟動探針、執行時錯誤、測試與映像檔行為;v25.2/v24.12 起能力穩定、v26 移除實驗轉換開關。生產服務只有在矩陣驗證通過後才切換,並保留編譯產物回滾。

常見錯誤

  • 把型別擦除當成型別檢查或完整編譯。
  • 直接執行含列舉、裝飾器、參數屬性或執行時 namespace 的檔案。
  • 依賴 tsconfig 的 paths、target 轉換或 JSX 設定。
  • 省略 import type,導致擦除後發生值匯入錯誤。
  • 讓生產映像檔執行 node_modules 中未編譯的 TypeScript。
  • 只測啟動速度,不執行型別檢查、整合測試與舊版本矩陣。

追問及應對

為什麼型別擦除通常不需要 source map?

實作透過替換為空白保留原始字元位置,執行時行號通常仍對應原始檔。需要轉換語法時仍應使用完整編譯器與 source map。

什麼時候必須保留 tsx 或編譯器?

需要列舉、裝飾器、參數屬性、paths、target 轉換、完整型別檢查或處理 TypeScript 依賴套件時,內建擦除無法滿足契約,應保留工具鏈。

如何控制 Node 版本差異?

在映像檔、CI 與本地工具中固定版本並做能力探測;把 type stripping 視為執行時前置條件,失敗時執行已驗證的 JavaScript 編譯產物路徑。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

截圖題目後,依序看約束、解法、程式碼、邊界條件和複雜度。

查看工具