編碼面試:如何安全遷移到 TypeScript 7 原生編譯器?
題幹與適用場景
你的團隊在一個 TypeScript 6 monorepo 中維護 Web 應用與共用套件。CI 型別檢查耗時過長,儲存庫同時使用 typescript-eslint、webpack loader,以及 Vue、Angular 範本工具。現在要評估 TypeScript 7 原生編譯器。
請設計遷移方案,說明如何保留 TypeScript 6 相容層、安排 CLI 與編輯器升級、控制平行檢查的記憶體風險,並定義灰度、指標與回滾條件。
面試官考察點
- 能否區分
tsc命令列、編輯器語言服務與程式化 TypeScript API 的依賴。 - 能否用鎖定版本、雙編譯器與可比較產物降低遷移風險。
- 能否把平行度、記憶體、診斷差異與生態相容性轉化為可執行的發布門檻。
- 能否說明 TypeScript 7 尚未提供穩定程式化 API 時的邊界。
回答前需要釐清的問題
- 目前 CI 使用的是
tsc --build、獨立專案還是自訂編譯器 API? - 哪些工具直接匯入
typescript,哪些只讀取宣告檔或命令列輸出? - 是否已啟用 TypeScript 6 的
stableTypeOrdering,並保存宣告、診斷與建置時間基線? - 編輯器版本、Node 記憶體上限與 CI runner 的 CPU/記憶體規格是否固定?
30 秒回答
我會先盤點所有 TypeScript API 消費者,再把 TypeScript 7 CLI 與 TypeScript 6 相容包並行安裝,鎖定版本和 lockfile。先在 CI 比對宣告檔、診斷、產生 JavaScript、source map、測試結果與資源用量;TypeScript 6 側先啟用 stableTypeOrdering。TypeScript 7 的 --checkers、--builders 只按基準逐步調大,並保留 --singleThreaded 作為診斷開關。沒有穩定程式化 API 的 Vue、MDX、Astro、Svelte、Angular 工具繼續使用 TypeScript 6。透過 canary、編輯器分批和明確回滾版本推進,達標後才擴大範圍。
分步驟深入解答
盤點編譯器與 API 依賴
記錄 Node、套件管理器、TypeScript、tsconfig、project references、loader、外掛與編輯器版本。把消費者分為 CLI、宣告/生成產物、語言服務和程式化 API;程式化 API 需要單獨的相容性驗證。
採用 TypeScript 7 與 TypeScript 6 雙軌安裝
TypeScript 7 目前提供原生編譯器,但還沒有穩定 API。可以讓 tsc 使用 7,同時用 npm alias 保留 tsc6:
{
"devDependencies": {
"@typescript/native": "npm:typescript@^7.0.2",
"typescript": "npm:@typescript/typescript6@^6.0.2"
}
}實際儲存庫應固定經過驗證的版本並提交 lockfile;腳本要明確呼叫對應二進位檔,避免套件管理器扁平化後誤用編譯器。
建立可比較的產物基線
先在 TypeScript 6 啟用 stableTypeOrdering,保存 .d.ts、診斷、產生 JavaScript、source map、增量建置快取和測試結果。比較時區分排序變化、真實型別錯誤和工具自身格式差異;只把可解釋且不影響 API 的變化納入允許清單。
調節 checker 與 builder 平行度
TypeScript 7 的 checker 預設使用 4 個 worker;builder 也可平行。先以固定 CPU、記憶體與專案順序測量,再逐級提高平行度。記錄牆鐘時間、峰值 RSS、GC 和失敗重試;超過 runner 記憶體預算就回退。遇到非確定性時用 --singleThreaded 重現並保留固定 worker 數作為 CI 設定。
隔離生態工具與編輯器升級
沒有穩定程式化 API 時,不要強迫範本工具一起升級。Vue、MDX、Astro、Svelte、Angular 等工具可能仍依賴 TypeScript 6 API,可讓它們繼續消費 tsc6 或維持獨立的 TS6 語言服務。編輯器先在少量開發者頻道啟用對應擴充功能,觀察補全、跳轉、診斷與崩潰率。
灰度、指標與回滾
先選擇低風險套件和一條 CI canary,比較建置時間、診斷差異、宣告相容性、記憶體峰值、編輯器錯誤與測試通過率。失敗時恢復舊 lockfile、舊腳本和 TS6 editor channel;不要只刪除 TS7 套件而留下不匹配的 loader。等所有門檻連續通過後再擴大到其他 workspace。
高品質示範回答
TypeScript 7 的價值在於原生編譯器和更快的 CLI,但遷移的邊界由 API 消費者決定。我會建立「TS7 做 CLI、TS6 做相容層」的雙軌方案:鎖定兩個版本,明確提供 tsc 與 tsc6,並將 loader、範本工具和編輯器按是否依賴程式化 API 分流。基線階段先啟用 stableTypeOrdering,逐項比較宣告、診斷、生成物、source map、測試和資源用量。平行參數按固定 runner 基準調優,--singleThreaded 用於重現問題。透過 canary、編輯器小流量和連續通過門檻後逐步擴大;任何診斷回歸、宣告破壞、記憶體超限或編輯器故障都觸發回滾。由於 TypeScript 7 還沒有穩定程式化 API,保留 TS6 直到生態工具完成適配,才是可逆的發布路徑。
常見錯誤
- 只替換
typescript版本,卻沒有檢查 loader、外掛和範本工具是否匯入 TypeScript API。 - 把所有速度提升歸因於原生編譯器,沒有記錄本儲存庫基線和記憶體成本。
- 未啟用
stableTypeOrdering就把宣告排序變化當成型別回歸。 - 讓 CI 追求最大平行度,忽略 runner 記憶體和失敗重試。
- 因為 CLI 能執行,就假設編輯器和程式化 API 已經相容。
- 只準備「解除安裝 TS7」的口頭回滾,沒有保留 lockfile、腳本和編輯器版本。
追問及應對
如果某個 loader 依賴 TypeScript 6 API,能否只升級 CI?
可以先只升級型別檢查 canary,loader 繼續呼叫 tsc6 或 TypeScript 6 API;必須驗證生成物和宣告檔一致,再決定是否升級 loader。
--checkers 越大越好嗎?
不一定。平行度受 CPU、記憶體、專案圖和 GC 影響,應以固定 runner 的牆鐘時間和峰值 RSS 共同決定,並保留較小值作為回退設定。
什麼時候可以移除 TypeScript 6?
當所有程式化 API 消費者、範本工具、編輯器和建置外掛完成相容性驗證,且 canary 指標連續達標;TypeScript 7 穩定 API 可用後再評估移除相容層。
如何證明型別結果沒有變化?
比較診斷、宣告檔、生成 JavaScript、source map 與測試結果,並對排序變化和格式差異做分類;不能只比較退出碼。