具代表性的面試主題

編碼面試:TypeScript 6.0 的 stableTypeOrdering 如何用於 6→7 遷移?

程式題困難
Offer.cc 編輯團隊發佈 更新

題幹

升級 TypeScript 6.0 後,團隊發現無關程式碼移動會改變聯合型別順序並觸發或消除型別錯誤。請解釋 --stableTypeOrdering 的用途、代價與邊界,並設計從 6.0 遷移到 7.0 的驗證方案。

題幹與適用場景

一個大型 TypeScript monorepo 準備從 5.9 升到 6.0,之後繼續評估原生編譯器路線。團隊發現只移動一個無關宣告,產生的 .d.ts 聯合型別順序就改變,某些推斷錯誤也隨之出現或消失。請說明 --stableTypeOrdering 為何存在、它不是長期最佳化開關的原因,以及如何在不擴大升級風險的情況下定位真實型別問題。

TypeScript 6.0 文件說明,該選項用來診斷 6.0 與 7.0 之間的型別排序差異,讓排序行為符合 7.0,但可能明顯拖慢型別檢查,最高約 25%。它不是長期預設設定;遇到差異時應優先加入明確型別參數或註解,並保留可重現的對照建置。

面試官考察點

面試官會關注你是否理解宣告產生與型別編號的關係,能否區分順序變化、真實型別錯誤與工具鏈雜訊。高品質回答還要涵蓋 project references、增量快取、產生檔案稽核、效能基線、CI 回滾與編譯器版本鎖定。

回答前需要釐清的問題

  • 變化發生在 .d.ts 輸出、編輯器顯示,還是實際賦值錯誤?
  • 專案是否使用 project references、增量建置或產生程式碼?
  • 6.0 與目標 7.0 編譯器、tsconfig 及依賴版本是否完全鎖定?
  • 型別檢查變慢的預算是多少,哪些套件最容易放大成本?
  • 升級失敗時能否回到 5.9 或關閉實驗選項?

30 秒回答

「我會把 --stableTypeOrdering 當作 6→7 遷移診斷工具,而不是永久效能開關。TypeScript 6.0 的型別編號會受到宣告處理順序影響,因此無關改動可能改變聯合型別輸出,甚至暴露隱藏的推斷依賴。先用不帶選項與帶選項的鎖定建置比較 .d.ts、錯誤與耗時;對穩定差異補明確型別參數或註解,避免依賴順序。若檢查變慢或產生器不相容,就縮小到受影響專案並保留 5.9 回滾。」

分步驟深入解答

1. 固定編譯器與輸入

鎖定 TypeScript、Node、套件管理器、tsconfig、依賴樹與產生腳本。對同一提交分別執行 5.9、6.0 預設模式、6.0 --stableTypeOrdering,再執行目標 7.0 預覽工具鏈;保存錯誤、宣告檔雜湊、檢查時長與快取命中率。

2. 解釋順序漂移的來源

編譯器內部會依處理順序為型別分配編號,並據此排序聯合型別與宣告輸出。加入無關字面量宣告可能改變編號,讓 .d.ts100 | 500 變成 500 | 100。順序改變不一定影響執行時,但若程式依賴脆弱推斷,就可能使錯誤出現或消失。

ts
export function choose(flag: boolean) {
  return flag ? 100 : 500;
}

// 無關宣告可能改變宣告檔中字面量聯合的排列順序。
const unrelated = 500;

不要把宣告檔文字順序直接當成語義差異;應進一步檢查消費者賦值、型別參數推導與 API 相容性。

3. 正確使用 stableTypeOrdering

該選項讓 6.0 的排序行為更接近 7.0,用來暴露跨版本差異。它可能帶來最高約 25% 的型別檢查減速,因此應只在遷移分支、受影響專案或診斷任務中啟用。記錄啟用範圍,避免讓全倉庫 CI 變慢卻沒有可行動結果。

4. 將隱式推斷改成明確契約

如果選項揭示某個呼叫依賴型別處理順序,優先加入明確型別參數、變數註解、公共回傳型別或泛型約束。修改後同時檢查 .d.ts、project references 與下游消費者,確保修復的是契約而非單純改變排序。

5. 驗證產生與增量路徑

在 project references、declaration、程式碼產生器、編輯器語言服務與增量快取下重複建置。清空快取再跑一次,區分排序差異與快取污染;對產生檔案做穩定性檢查,但不要把格式化後的宣告檔當作唯一測試指標。

6. 設定遷移閘門與回滾

透過條件建置矩陣比較錯誤數量、宣告 API、檢查耗時與發佈套件差異。只有 6.0/目標 7.0 結果可解釋、公共 API 無意外變化且效能在預算內,才擴大範圍。任何嚴重回歸都關閉選項、回到 5.9 或預設排序,並保留提交級對照證據。

高品質示範回答

我會先鎖定工具鏈與輸入,建立 5.9、6.0 預設、6.0 --stableTypeOrdering 與目標 7.0 的四路矩陣。該選項用來讓 6.0 型別排序接近 7.0,協助發現宣告順序與推斷差異,但可能讓型別檢查變慢,不能長期全域啟用。比較 .d.ts、真實錯誤、project references、產生器與快取行為;對暴露出的隱式推斷補明確型別參數或註解。只有 API、效能與回滾閘門都通過,才繼續遷移。

常見錯誤

  • 把聯合型別順序變化當成執行時變化 → 混淆宣告表示與執行語義 → 繼續驗證消費者型別與 API 相容性。
  • 全倉庫永久開啟 --stableTypeOrdering → 可能增加約 25% 檢查時間 → 限定在遷移或診斷矩陣。
  • 只比較編輯器顯示 → 忽略宣告產生與下游建置 → 稽核 .d.ts、references 與發佈套件。
  • 為讓 CI 變綠而改排序 → 隱藏脆弱推斷 → 補明確型別契約並保留對照結果。
  • 沒有 5.9 回滾 → 升級失敗時無法快速定位 → 鎖定版本並準備條件建置。

追問及應對

為什麼無關宣告會影響聯合型別順序?

TypeScript 會按處理過程分配的型別編號排序;無關宣告可能改變編號。順序變化通常是宣告輸出層面的差異,但它可能暴露原本依賴推斷順序的程式碼。

該選項應該一直開啟嗎?

不應該。文件把它定位為 6.0 到 7.0 的診斷輔助,可能明顯減慢檢查;遷移完成後應回到正常設定。

如何判斷是真錯誤還是排序雜訊?

在鎖定輸入上比較預設與穩定排序的錯誤、.d.ts、下游賦值與執行時無關的型別契約。只有消費者無法滿足契約或公共 API 改變,才需要程式修復。

為什麼優先加明確型別參數?

明確參數把意圖寫進原始碼,消除對處理順序的隱式依賴,也讓 6.0、7.0 與編輯器更容易產生一致結果。

什麼時候可以結束遷移診斷?

當目標工具鏈的型別結果可解釋、宣告 API 穩定、產生與增量路徑通過、效能在預算內並有回滾證據時,才關閉診斷選項並繼續正式升級。

公開來源

同類題目

相關面試工具

用 Screenshot 處理演算法題

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

查看工具