型別繼承
物件型別可以繼承一個或多個父物件型別。子型別會繼承每個父型別的每個欄位,並可以用同名重新定義覆寫掉任何繼承的欄位。這在兩個型別有大部分共同 shape、只有少數欄位不同的情況下最對味——不用再把 id、createdAt、updatedAt 在十幾個相似型別裡重複寫一遍。
繼承是可選的:沒有 extends 的型別跟以前一模一樣。
宣告 extends
在型別建構器選一個物件型別,欄位清單上方會出現新的 Extends 標籤選擇器。從下拉式選單挑一個父型別,它會變成一個標籤;再挑一個就多一個父型別;點標籤上的 × 移除。
候選父型別已經幫你篩過了:
- 只有其他物件型別會出現(primitive、union、array 不能被繼承)。
- 當前選中的型別不能選自己。
- 任何會形成循環(
A extends B extends A)的父型別會自動排除。
父型別如果之後被刪除或改成非物件 kind,會在型別建構器上方的警告列裡顯示為 broken ref——跟 $ref 斷掉的處理一樣。
父型別標籤可以拖拉重排以調整優先順序:抓起一個標籤拖到另一個上,或用鍵盤拖拉(Space 抓取、方向鍵移動、Space 放下、Escape 取消)。
繼承欄位面板
一個型別至少有一個父型別後,標籤列下方會多一個繼承欄位面板,一行一個,從整條父鏈聚合後以淡灰呈現。每行顯示欄位名、kind 徽章、是否必填,右側有一個 Override 按鈕。
點 Override 會把這個繼承欄位複製到子型別的 fields[] 裡當作一個新行,預先填好父型別的定義。繼承面板裡的那行會消失(因為子型別現在自己擁有了),而子型別裡的那行會多一個 (override) 徽章和一個小小的 Revert(↶)按鈕。
- 覆寫過後的欄位可以像其他欄位一樣編輯——改型別、翻轉必填、調整 constraints。子型別的定義會贏。
- 點 Revert 會移除覆寫、還原成父型別的定義。這行會回到繼承面板裡。
覆寫語意
- 子型別完勝:名字跟父型別相同的欄位,覆寫是完整重新定義,沒有部分合併。
- 優先順序:父型別按照你挑選的順序由左到右合併,後面的父型別蓋掉前面的,子型別蓋掉全部。所以
Foo extends [Bar, Baz]加上Bar: {x, y}、Baz: {y, z}、childFoo: {z, w}的結果是:
x — 來自 Bar
y — 來自 Baz(覆寫 Bar)
z — 來自 Foo(覆寫 Baz)
w — 來自 Foo(新增)- strict 模式是 OR 聚合的。 只要整條鏈上有任何一個標 strict,最終型別就是 strict。子型別可以自己標 strict,但無法把父型別的 strict 取消掉。
- 不能移除繼承的欄位。OpenAPI
allOf沒有「減掉某欄位」的語法。如果想要沒有某個欄位的父型別版本,就不要繼承它。 - 沒有 generic / 條件繼承。 只有單純的結構繼承。
消費者看到什麼
任何需要有效 shape(相對於宣告層級)的地方,應用會即時攤平:
- Runtime 驗證會檢查繼承下來的必填欄位。缺少父型別
id的 response 會被拒絕。 - Run panel 的範例生成會走遍整條鏈,所以繼承的欄位也會出現在初始 payload 裡。
- 規格差異比較的是解析後的 shape,所以把平鋪型別重構為
Foo extends Base且最終 shape 不變會得到空的 diff。
型別建構器本身不攤平——它一直展示你宣告的層級,讓你自然地繼續編輯。只有繼承欄位面板會透過 resolver 算出結果。
OpenAPI 來回保真
繼承直接對應到 allOf:
User:
allOf:
- $ref: '#/components/schemas/Base'
- type: object
properties:
name: { type: string }
required: [name]- 匯出——父型別變成
$ref;子型別自己的欄位(如果有的話)會落在一個 inline object 成員裡。只繼承不加欄位的型別會匯出成allOf: [...refs],沒有 inline 成員。 - 匯入——allOf 裡有一個或多個
$ref加上最多一個 inline object 會被還原成{ extends: [...refs], fields: inline.fields }。allOf 裡只有多個 inline object、沒有$ref的情況會走舊的「攤平合併」邏輯,這樣這個功能出現之前的歷史規格仍然可以讀。 - 有資料夾的父型別會用攤平鍵的形式匯出(鍵為
auth/Base的父型別會變成auth_Base),並用x-folderextension 在匯入時還原路徑。
JSON Schema 與 Markdown
- JSON Schema 匯出使用相同的
allOf模式,用#/$defs/…來參考。 - Markdown 匯出會在每個有繼承的型別 JSON skeleton 之前加一行 Extends:,每個父型別都是跳到該段落的可點擊連結。param tables 裡的 ref 現在也是可點擊的錨點。
從平鋪型別遷移
如果你已經有一個複製了另一個型別欄位的平鋪型別,遷移是一個小編輯:
- 保留父型別不動。
- 在型別建構器開啟子型別,在 Extends 選擇器加上父型別。
- 凡是已經跟父型別定義一樣的欄位,從子型別裡刪除(繼承那一行會自動回來)。
- 凡是不一樣的欄位留下——它們就是 overrides。
跟遷移前的版本跑一次規格 diff 來確認語意沒變。空的 diff 代表重構是安全的。
繼承不做的事
- 不支援非物件的 extends。 只限物件型別。
- 不能移除繼承的欄位。 OpenAPI 沒辦法表達減法。
- 沒有 generic / 條件繼承。 只有單純的結構繼承;沒有型別參數。
- 沒有「最終 shape」預覽面板(延後的 polish)。繼承面板與 override 列已經足以看到全貌。