notes mizzy.org

構造体を封印すると打ち間違いは捕まるがスキーマ進化に弱くなる

確認済み 出典: audits/2026-05-23-type-system-evaluation.md §2.3, §3.2 (g), §6 作成

構造体の値検証は、必須フィールドの存在を確かめ、未知のフィールドを拒否する(似た名前があれば候補として提示する)。つまり幅部分型付け(width subtyping)を負の方向にしか許さない。フィールドを減らすことはできず、増やすこともできない、封印された(sealed)構造体である。Flowの完全型{| ... |}やRustの構造体リテラルに近い扱いになる。

これは意図した設計である。IaCでは打ち間違いが最も多い誤りで、未知フィールドを黙って捨てる言語では「書いたのに効いていない」という最悪の失敗モードが生まれる。封印はこれを構文の位置で捕まえる。

代償はスキーマの進化速度

代償ははっきりしている。プロバイダのスキーマが新しいフィールドを増やしたとき、コード生成が追いつくまでそのフィールドは書けない。クラウドAPIは絶えず属性を足すので、この追従は継続的なコストになる。実際、コード生成で都度追従する運用になっている。

つまり交換されているのは打ち間違いの検出スキーマ進化への耐性であり、封印はこの二つのうち前者に全振りした選択である。

封印 (sealed) — 現状の既定 打ち間違いを構文の位置で捕まえる 新フィールドは生成が追いつくまで書けない 規則がコードに埋まっている 開いた (open) 様式 進化の速いスキーマに追従できる 打ち間違いが素通りしうる 今は選択肢として存在しない 開閉を型の属性にする 既定値は封印のまま、緩めたい型だけ型の側で宣言する 例外が検証器の 分岐ではなく型の値になる
二者択一に見えるのは、開閉が型ではなく検証器のコードに埋まっているからである。型の属性に上げれば、既定値を動かさずに例外を作れる。

中間はありうる

この交換は二者択一ではない。構造体に「開いた(open)」様式を導入し、どの構造体が未知フィールドを受けるかを型の側で宣言できるようにすれば、封印の既定値を保ったまま進化の速いスキーマだけ緩められる。判定が「どこでも同じ規則」から「型に書かれた規則」に移るだけで、検査の一貫性は保たれる。

これは「区別を型に昇格させる」という解の形の、もう一つの適用先である。現状は「全ての構造体は封印されている」という規則がコードに埋まっており、例外を作ろうとすれば検証器を分岐させるしかない。開閉を型の属性にすれば、例外は分岐ではなく型の値になる。

根拠の確度

「コード生成で都度追従している」という運用上の観察は評価メモの記述に依拠しており、追従の遅れが実際にどの程度の負担になっているかの計測はない。

#型システム #部分型 #トレードオフ