
開發契機:某個下午的「虛無感」
在現代 Web 開發中,毫不誇張地說,前端工程師有一半的工作是在「與 API 對話」。在 Postman 或 Swagger 確認 API 回應,然後將其改寫為 TypeScript 的 interface 或 type 定義……
某個下午,我盯著一個具有複雜層級的龐大 JSON 回應,手指突然停了下來。
「我現在到底是為了什麼,在逐字輸入這些屬性名稱?這項工作中,有身為工程師的創造性存在嗎?」
專案規模越大,回應的層級就越深,輸入錯誤 (Typos) 的風險也隨之增加。我想要從這種「重複勞動」中解放自己。
「無需設定,貼上的瞬間就能得到令人滿意的型別定義。」我想要一個像「工匠工具」般順手的工具,於是開始了 JSON to TypeScript 轉換工具 的開發。
技術巧思:遞迴演算法的「美學」
這款工具最大的挑戰在於:「不使用任何肥大的外部函式庫,純粹靠邏輯實現專業水準的精確度。」
1. 走訪無盡嵌套的「遞迴處理」
JSON 的結構就像大盒子裡面套著小盒子。不管嵌套得有多深,都必須在一瞬間到達最深處。為了應對這種「不確定的深度」,我採用純遞迴處理來構建演算法。
private static inferType(value: any, depth = 1): string {
// 基本原始型別判定
if (value === null) return 'null';
// 若為陣列,則再次全量遍歷內部內容
if (Array.isArray(value)) return this.formatArray(value, depth);
// 若為物件,則遞迴走訪屬性
if (typeof value === 'object') return this.formatObject(value, depth);
return typeof value;
}
透過對這個簡單結構的精雕細琢,我變得能夠在一瞬間為極其複雜的資料結構生成強韌的型別定義。
2. 對「聯合型別 (Union Type)」的執著
開發過程中最讓我苦惱的是對陣列 (Array) 的處理。
例如有一個陣列為 [1, "text", null],如果只是簡單地產出 any[] 那也太敷衍了。但如果只看第一個元素就武斷地判定為 number[],那也極其不體貼。
在本工具中,我加入了一套邏輯:先掃描陣列中所有元素的型別,去重後,以 |(豎線)連結形成聯合型別輸出。
const types = Array.from(new Set(arr.map(item => this.inferType(item))));
const union = types.length === 1 ? types[0] : `(${types.join(' | ')})`;
return union + '[]'; // 結果: (number | string | null)[]
我深信,這種「細節處的體貼」正是大大影響實際開發場景使用體驗的關鍵。
對「看不見的地方」的關懷
我也非常執著於轉換結果的「美觀」。
反覆微調文字細節——例如縮排深度、鍵名 (Key name) 的引號處理等。目標是達到一種品質:讓您能「將轉換後的代碼直接貼入專案並提交,甚至不需要執行一次 Formatter」。
結語
JSON→TypeScript 轉換工具乍看之下是個樸素的工具。但在其背後,蘊含著「遞迴處理的美學」,以及「不讓工程師浪費哪怕 1 分鐘時間」的強烈執著。
將您的開發時間從單純的「抄寫型別」轉換為「構建有價值的代碼」。希望這款工具能為此貢獻一份微薄的力量。