domain-language-types について
問題領域の概念に基づいて型に名前を付ける、TypeScript 開発向けのスキルです。ドメインエキスパートにも意味が伝わる型の作成やレビューに役立ちます。
主な機能
- 01ドメイン用語で型を命名
- 02構造を示す名前を意味ある名前に変更
- 03ハンガリアン記法の接頭辞や冗長な接尾辞を回避
- 04ドメインで共有される用語を採用
活用シーン
- 01新機能の型命名
- 02不明瞭な型名のリファクタリング
- 03ドメインエキスパートとの API レビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marius-townhouse/ effective-typescript-skills --skill domain-language-typesインストール後、Claude Code で/domain-language-typesを入力して読み込まれたか確認します。
詳細
問題領域の言葉を使って型に名前を付ける
概要
型名は構造ではなく、意味を伝えるべきです。
INodeNameValueData という名前の型からは何も分かりません。一方、APIResponse や CustomerOrder という名前の型からは、すべてが分かります。データ構造の言葉ではなく、ビジネスドメインの言葉を使いましょう。
このスキルを使う場面
- 新しい型に名前を付けるとき
- 分かりにくい型名をリファクタリングするとき
- ドメインエキスパートとコードをレビューするとき
- 公開 API を設計するとき
絶対的なルール
Type names should be meaningful to domain experts.
If a non-programmer can't understand it, rename it.
覚えておきましょう:
- 技術用語よりビジネス用語
- 構造より意味
- 名前はドキュメント
- ドメインエキスパートが型を理解できること
判別:構造を表す名前
// Bad: describes structure, not meaning
interface IEntityWithIdAndName {
id: string;
name: string;
}
interface IStringPairList {
items: [string, string][];
}
interface IDataRecord {
data: Record<string, unknown>;
}
IEntityWithIdAndName とは何でしょうか? ユーザーでしょうか? 商品でしょうか? カテゴリーでしょうか?
より良い例:ドメインを表す名前
// Good: describes what it IS
interface User {
id: string;
name: string;
}
interface TranslationPairs {
items: [sourcePhrase: string, targetPhrase: string][];
}
interface CustomerProfile {
data: Record<string, unknown>;
}
実例:E コマース
// Bad: generic/structural names
interface IData {
id: string;
props: Record<string, unknown>;
}
interface IEntity extends IData {
type: string;
}
interface ICollection {
items: IEntity[];
total: number;
}
と、
// Good: domain language
interface Product {
sku: string;
name: string;
price: Money;
inventory: number;
}
interface Order {
orderNumber: string;
customer: Customer;
items: OrderItem[];
total: Money;
}
interface ProductCatalog {
products: Product[];
totalCount: number;
}
避けるべきパターン
ハンガリアン記法のプレフィックス
// Bad: I prefix for interfaces
interface IUser { }
interface IProduct { }
// Good: just the name
interface User { }
interface Product { }
型を表すサフィックス
// Bad: redundant suffixes
interface UserType { }
interface ProductInterface { }
interface OrderObject { }
// Good: clean names
interface User { }
interface Product { }
interface Order { }
汎用的な技術用語
// Bad: generic
interface DataModel { }
interface EntityRecord { }
interface ItemContainer { }
// Good: specific
interface Invoice { }
interface ShippingAddress { }
interface ShoppingCart { }
プロパティ名も同様です
// Bad: technical property names
interface User {
dataString: string;
valueNumber: number;
itemsArray: Product[];
}
// Good: domain property names
interface User {
email: string;
age: number;
purchases: Product[];
}
コンテキストが重要です
構造が同じでも、ドメインが違えば名前も異なります。
// Healthcare domain
interface Patient {
mrn: string; // Medical Record Number
admissionDate: Date;
diagnosis: string[];
}
// Education domain
interface Student {
studentId: string;
enrollmentDate: Date;
courses: string[];
}
構造は似ていますが、名前は異なる意味を伝えています。
技術的な名前が許容される場合
標準的な技術概念
// OK: widely understood technical terms
interface HttpRequest { }
interface DatabaseConnection { }
interface CacheEntry { }
汎用ユーティリティ
// OK: truly generic utilities
type Nullable<T> = T | null;
type AsyncResult<T> = Promise<T>;
内部実装
// OK for internal implementation details
interface InternalCacheNode<T> { }
interface TreeNodeImpl<T> { }
ユビキタス言語
ドメイン駆動設計では、開発者とドメインエキスパートの双方が共有する「ユビキタス言語」を使います。
// If domain experts say "fulfillment", use that:
interface OrderFulfillment { }
// Not:
interface OrderProcessingData { }
interface IOrderExecutionEntity { }
圧力に負けないためのプロトコル
1. 「技術的な詳細にすぎません」
圧力:「ユーザーはこの型名を見ません」
回答: 開発者は見ます。未来の自分も見ます。意味のある名前にしましょう。
アクション: 構造ではなく、何を表すのかに基づいて名前を付けましょう。
2. 「命名規則があります」
圧力:「スタイルガイドでは I を付けることになっています」
回答: 規則は明確さを損なうのではなく、明確さを支えるべきです。
アクション: 明確さを損なう規則には異議を唱えましょう。IUser には何も付け加えるものがありません。
危険信号 — 作業を止めて再考しましょう
- I、T で始まる型名、または Type/Interface/Object で終わる型名
- 構造を説明する名前(StringArray、NumberMap)
- ドメインエキスパートが理解できない名前
- どれも「Data」と呼べてしまう複数の型
よくある正当化(すべて無効)
| 言い訳 | 実態 |
|---|---|
| 「バックエンドと一致しています」 | バックエンドの名前も適切とは限りません |
| 「内部でしか使いません」 | 内部コードにも明確さが必要です |
| 「これが規則です」 | 悪い規則は変えるべきです |
クイックリファレンス
// DON'T: Structural/technical names
interface IDataEntity { }
interface StringValuePair { }
interface ItemsCollection<T> { }
// DO: Domain language names
interface Customer { }
interface PriceRange { } // [min: Money, max: Money]
interface ProductCatalog { }
// DON'T: Redundant suffixes
interface UserType { }
interface ProductInterface { }
// DO: Clean names
interface User { }
interface Product { }
要点
構造ではなく、意味に基づいて型に名前を付けましょう。
ドメインエキスパートが型名を読んで、それが何を表すのか理解できるようにしましょう。Invoice は IFinancialDataRecord より多くのことを伝えます。問題領域の言葉を使いましょう。
参考文献
Dan Vanderkam 著『Effective TypeScript』の項目 41「問題領域の言葉を使って型に名前を付ける」に基づいています。