
TSの書き方を覚えたら、実際に仕事で使えるようにするには、経験を積むしかありません。
仕事でしか経験を積めないと考えている人がいたとしたら、プログラミング学習がめちゃくちゃ効率悪く進んでしまう人でしょう。
プログラミングの上達の早い人というのは、大きな特徴があり、「自分で作りたいものを作る(プログラミングする)」人は、放っておいてもどんどん自分で経験値を上げていくことができる。
ドラクエで言うところの、"幸せの靴"を履いている状態に慣れるんですよね。
そんなわけで、このブログでは、型設計についての経験の積み方を解説してみたいと思います。
「プロジェクトレベルで型設計する」とは?
TypeScriptで、小さい関数に型をつけると言うだけでは、プロジェクト全体での威力が発揮できないので、次のような問題が発生します。
・API仕様が変わった
・UIコンポーネントが複雑化した
・ロジックや責務が分散して管理不能
・型が循環参照し始める
・似た型が乱立して地獄になる(User, UserEntity, UserResponse, UserModel…)
そこで、必要になるのが、
プロジェクト全体を俯瞰して、型をドメイン単位・レイヤー単位で設計する視点です。
鉄板の型設計「階層モデル」
| レイヤー |
目的 |
例 |
| Primitive Layer |
string / number / boolean の基本型 |
`string`, `number` |
| Domain Value Objects |
意味を持つ型 |
`UserId`, `Email`, `Price` |
| Data Structures (DTO) |
API / DB / external schema |
`UserResponse`, `DBRecord` |
| Domain Models |
ビジネスロジック層の型 |
`User`, `Order`, `CartItem` |
| UI Types / Props |
React / UI表示用 |
`UserViewProps`, `SelectableOption` |
DB・APIの型とアプリ内部の型を区別することが重要です。
API→ドメイン→UI の型変換サンプル
APIデータ
type UserResponse = {
id: number;
name: string;
mail_address: string; // snake_case
}
これをそのまま使うのは、アンチパターンです。
プロジェクト型設計があると以下のようになります。
ドメイン
type Email = string;
type User = {
id: number;
name: string;
email: Email;
}
UI
type UserViewModel = {
id: string
displayName: string
}
変換関数
function toDomain(res: UserResponse): User {
return {
id: res.id,
name: res.name,
email: res.mail_address
}
}
function toViewModel(user: User): UserViewModel {
return {
id: String(user.id),
displayName: `${user.name} `
}
}
これで、API変更に強いコードになり、UIの自由度上がります。
型が責務を分離する使い方ができるのがポイントですね。
型を資産化する
プロジェクトレベルでは、型は「辞書」や「ルールブック」の役割になります。
例:状態管理のステートマシン
type LoadState =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: User }
| { status: "error"; message: string }
型設計が強いと何が変わる?
・ドキュメントを書かなくても意図が共有される
・新規メンバーが迷わない
・リファクタリングが怖くない
・API変更・仕様変更に強くなる
・テストコードが減る(型がテストの代わりになる部分がある)
プロジェクトがデカくなるほど、型が意思決定を支配し、コードの整合性を維持してくれるようになります。
型設計の練習ステップ
実際に、型設計の経験を積むためには、次の分類行い、下のステップで行うのが良いでしょう。
小規模 → 型を付ける練習
中規模 → 型を再利用・抽象化
大規模 → 型を設計する
1. 型 alias(type)整理
2. DTOとDomainを分ける
3. Union/Intersectionで状態表現
4. Genericsで共通ロジック抽象化
5. Utility TypesでDRY化
6. Conditional / Mapped Typesで柔軟化
あとがき
TSの本質は“コードを安全にする”ことではなく、“設計を守る仕組みを作ること”だと考えても良いかもですね。
そして、「プロジェクトレベルの型設計」ができるようになる事が重要です。
TSを単なる型付けシステムと言うのではなく、「設計思想」と「仕様管理システム」ぐらいに考えるのが良いかもしれませんね。
安定したシステムを作ると言うのは、やはり設計が重要なんですね。
0 件のコメント:
コメントを投稿