alunduil / alunduil/blog.alunduil.com

Deriving the type from the schema you actually serve

オープン
#459 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
idea
主要言語
Astro
スター
1
フォーク
1
平均マージ
6時間 34分
マージ済み PR(30日)
118

説明

## Spark

A sustained arc in genshin.dungeon.studio over the week of 2026-08-01: moving
validation out of runtime assertions and into types derived from the schemas
the API actually serves. Constellation level became a 0–6 union, character and
weapon IDs became unions derived from the roster, and the remaining issues push
the same treatment into refinement level, request-body narrowing, and the
deserialisers that currently let unvalidated wire properties through.

## Why it could be interesting

The activity is "add union types." The claim underneath is about where the
authority for a shape lives. Once TypeScript types are *derived from* the
served schema rather than hand-written alongside it, the schema stops being
documentation and becomes the single definition — and the classes of bug that
survive changes shape. `assertCollectionTeam` thinning out of the Firestore
read path (#1147) is the tell: when the type carries the invariant, the runtime
guard has less to do, and what's left is exactly the trust boundary.

The counter-pressure worth naming is that a derived type only protects the
boundary it derives from. Two of the open issues (#1143, #1144) are precisely
about deserialisers that type-check while leaking properties nobody validated —
the type says the right thing about data the code never actually checked.

## Open questions

- [ ] Explanation (why derived-from-schema changes the failure modes) or how-to
(wiring TypeBox so one definition serves JSON Schema and TypeScript)?
- [ ] What did TypeBox actually settle in #469, and is the decision durable
enough to write about?
- [ ] Is "unrepresentable illegal states" the right frame here, or is this
narrower — derivation and single-definition, not modelling?
- [ ] The honest limit: a derived type is only as good as the validation at the
boundary. Does the post need the #1143/#1144 failure as its second act?
- [ ] Overlap with #312 (compatibility across rolling deploys) and #252
(generated rosters) — sibling, subset, or one longer piece?

## Source material

- dungeon-studio/genshin.dungeon.studio#1149 (merged) / #501 (closed) — character and weapon ID unions derived from as-const arrays
- dungeon-studio/genshin.dungeon.studio#1146 (merged) / #498 (closed) — constellation level as a 0–6 union
- dungeon-studio/genshin.dungeon.studio#1148 — refinement level as a 1–5 union
- dungeon-studio/genshin.dungeon.studio#1145 (merged) / #504 (closed) — validate optional team fields
- dungeon-studio/genshin.dungeon.studio#1160 — `validateRequestBody` narrows to the schema-derived type
- dungeon-studio/genshin.dungeon.studio#1143 — deserialisers leak unvalidated wire properties
- dungeon-studio/genshin.dungeon.studio#1144 — `deserialiseArtifactPlan` rejects partial plans
- dungeon-studio/genshin.dungeon.studio#1147 — thin `assertCollectionTeam` out of the Firestore read path
- dungeon-studio/genshin.dungeon.studio#469 (closed) — TypeBox for unified JSON Schema and TypeScript
- dungeon-studio/genshin.dungeon.studio#1161 — DSGEP-003 records that types derive from the served schemas
- Also closed this window: #510, #506, #505
- Adjacent existing ideas: #312, #252, #329

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。