| id | type-driven-design |
| name | Type-Driven Design Guard |
| description | Detect primitive obsession and missing domain/brand types; check that state is modeled via discriminated unions. |
| version | 0.1.0 |
| category | midstream |
| phase | midstream |
| applyTo | ["src/**/*.{ts,tsx}","app/**/*.{ts,tsx}","lib/**/*.{ts,tsx}","packages/**/*.{ts,tsx}"] |
| tags | ["typescript","type-driven-design","domain-modeling","midstream"] |
| severity | major |
| inputContext | ["diff","fullFile"] |
| outputKind | ["findings","actions"] |
| modelHint | balanced |
| dependencies | ["code_search"] |
Pattern declaration
Primary pattern: Reviewer
Secondary patterns: Inversion
Why: プリミティブ型の濫用やドメイン型の欠如をチェックリスト型で評価するが、TypeScript以外の変更では実行不要
Goal / 目的
- 型を「仕様書」として扱い、ドメイン概念をプリミティブ型のまま放置しないようにする。
- 不正な状態を型レベルで表現不可能にする("make illegal states unrepresentable")。
Non-goals / 扱わないこと
any の排除や型アサーションの削減(typescript-strict のスコープ)。
- null/undefined のガードや非 null アサーションの排除(
typescript-nullcheck のスコープ)。
- 既存の関数シグネチャ(差分に含まれていない)のリファクタ提案。
tsconfig.json の設定変更。
- スタイル/命名規則のレビュー(nit は出さない)。
Pre-execution Gate / 実行前ゲート
このスキルは以下の条件がすべて満たされない限りNO_REVIEWを返す。
ゲート不成立時の出力: NO_REVIEW: type-driven-design — Type-Driven Design評価の対象となるTypeScriptコード変更が検出されない
False-positive guards / 抑制条件
- ブランド型がリポジトリに既に存在し、差分コードがそれを正しく使用している場合(
code_search で確認)。
string の引数が 1 つしかなく、他のプリミティブとの混入可能性がない場合。
- 外部 API レスポンスやライブラリ型を直接扱う境界コードで、ブランド型の適用範囲が明確でない場合(注記として返す)。
- 小さなユーティリティ関数で、ドメインの文脈を持たない場合。
Rule / ルール
- ドメイン概念を表す
string / number にはブランド型 (UserId, OrderId, Price 等) を使う。
- 複数の状態を
boolean フラグや status: string で表現するのではなく、判別可能なユニオン型(Discriminated Union)でモデリングする。
- 新規の public 関数/メソッドのシグネチャに
string / number が連続して並ぶ場合、引数が混入可能か確認する。
- リテラルユニオンが複数箇所でインライン定義されている場合、型エイリアスへの切り出しを促す。
Evidence / 根拠の取り方
- 指摘は差分に紐づける(
<file>:<line> で追える内容)。
- ブランド型が既にコードベースに存在するかを
code_search で確認し、根拠を示す。
- 推測を断定しない(不確実なら "可能性" として書く)。
Output / 出力
<file>:<line>: <message> 形式。コメントは日本語で返す。