在處理 API 回應的 TypeScript 開發中,對應 JSON 的型別定義無法迴避。一邊盯著巢狀很深的 JSON、一邊手寫 interface,既枯燥又是打錯字的溫床。

如何從 JSON 生成 TypeScript 型別:用實例學會轉換訣竅

本文以轉換範例展示 實際的 JSON 會變成什麼樣的 TypeScript 型別,並說明自動生成的訣竅與注意事項。

基礎:扁平物件的轉換

先從簡單的例子開始。

{
  "id": 42,
  "name": "Alice",
  "isActive": true
}

它會變成下面的型別。各值的型別(number / string / boolean)可以從實際值機械式地推導。

interface User {
  id: number;
  name: string;
  isActive: boolean;
}

含巢狀與陣列的轉換

實際的 API 回應會包含物件巢狀與陣列。

{
  "id": 42,
  "name": "Alice",
  "roles": ["admin", "editor"],
  "profile": {
    "age": 30,
    "city": "Tokyo"
  }
}

慣例是從元素型別將陣列定為 string[],並把巢狀物件拆成獨立的 interface。

interface Profile {
  age: number;
  city: string;
}

interface User {
  id: number;
  name: string;
  roles: string[];
  profile: Profile;
}

容易踩到的重點

null 與選擇性屬性

當 JSON 含有 null 時,光看那個值無法判斷該欄位是「總是可能為 null」還是「剛好這次為 null」。

{ "nickname": null, "deletedAt": null }

機械式轉換會得到 nickname: null,但實務上大多應是 string | nullnickname?: string生成後依 API 規格手動微調才是務實的做法。

interface User {
  nickname: string | null;   // 也可能會有值
  deletedAt?: string;        // 欄位本身可能不存在
}

注意以字串包裝的數字

"price": "1980" 這樣把數字以字串包裝的 API 並不少見。生成工具會將其推導為 string。若要在程式中運算,請將型別改為 number 或在接收後轉換,事先決定好方針。

空陣列無法決定型別

"tags": [] 這樣的空陣列無法推導元素型別,容易變成 never[]any[]。請使用含有元素的樣本,或在生成後手動指定為 string[] 等。

使用自動生成的步驟

  1. 從瀏覽器 Network 分頁或 curl 輸出複製實際的回應
  2. 貼到 JSON → TypeScript 型別生成工具
  3. 將根 interface 名稱由 Root 改成 UserResponse 之類
  4. 依規格調整 null 與選擇性欄位
  5. 貼回專案即完成

重點是使用盡量貼近正式、欄位齊全的樣本。樣本貧乏會漏掉選擇性欄位與型別的變動。

當型別不夠時,改用 Zod

TypeScript 的型別是「編譯期」的檢查。外部 API 實際回傳的資料未必符合你的型別。若也想在執行期驗證資料形狀,建議用 JSON → Zod Schema 生成 建立驗證 Schema,並以 schema.parse(data) 加上入口檢查。Zod 也能推導型別,讓你把型別與驗證統一管理。

常見問題

每次都要更改生成型別的根名稱,很麻煩。

多數工具會把根輸出成通用的 Root。最省事的做法是在複製後,用尋找取代換成專案的命名規範(ApiResponseUserProfile 等)。巢狀 interface 的名稱通常已貼合其內容,因此多數情況只改根即可。

想把 snake_case 的 API 當成 camelCase 使用。

生成的型別會原樣反映 JSON 的鍵,所以會得到 created_at 這類名稱。若要全專案統一為 camelCase,慣例是在 API 邊界處轉換(用對應函式或 camelize 類函式庫)。讓型別定義貼合 API 實體、並明確地進行轉換,就不會混亂。

TypeScript 型別與 Zod Schema,應該先做哪一個?

若需要執行期驗證,建立 Zod Schema 並用 z.infer 推導型別,可統一管理,較為推薦。若內部可信任資料只需編譯期檢查,僅生成 TypeScript 型別即可。對外部 API、表單輸入等「不可信任的輸入」使用 Zod 較安全。