評価軸: 「型でドメインルールを表現できる能力」×「その型制約が事前に検証できる保証」 (事前検証は、コンパイル時、静的解析時、実行前のいずれでも良い)
| 言語・環境 | スコア | 評価・理由 |
|---|---|---|
| Rust | 98 | 型による設計の極致 Sum types、Pattern matching、Trait boundsによる表現力は圧倒的。所有権システムが型レベルでメモリ安全性まで保証。ただし複雑なライフタイムは時に過剰な制約となる。完璧ではないが、現時点の到達点。 |
| PHP w/ Psalm/PHPStan | 90 | 静的解析による完成形 Plain PHPの実行時保証に加え、PHPDocで数値範囲、非空文字列、配列形状、純粋関数まで表現可能。開発時に型エラーを完全に排除できる。実行時とコンパイル時の区別は実用上重要ではない。型表現力と事前検証の両立。 |
| TypeScript | 88 | 開発時の最強の味方 Conditional Types、Template Literal Types、Mapped Typesによる型表現力は芸術的。実行時保証はないが、開発時の完全な型チェックにより問題を事前に排除。コンパイル時か実行時かの区別より、問題を見つけられるかが重要。zodとの組み合わせでIO境界も保護可能。 |
| Plain PHP (8.3+) | 80 | 実直な信頼性 readonly、Enum、DNF型など着実に進化。型宣言したものは実行時に100%守られる。表現力は限定的だが「嘘をつかない型システム」として信頼できる。大規模システムで予測可能性を重視する場合の隠れた優等生。 |
| Python w/ Pyright/Mypy | 75 | 漸進的型付けの現実解 Protocol、TypedDict、Literalによる表現力向上は評価できる。静的解析により開発時に型エラーを検出可能。実行時チェックがないのは事実だが、CI/CDパイプラインでの型チェック必須化により実用上は問題ない。Pydanticとの組み合わせが実質的標準。 |
| Ruby w/ Sorbet/RBS | 55 | 後付けの苦闘 メタプログラミング文化との相性の悪さが根本問題。型定義ファイルの分離は認知負荷を増やす。Sorbetのsigは侵襲的。Rubyの良さを殺さずに型を付ける困難さの表れ。 |
| Go | 48 | シンプルさの代償 Generics追加後も型表現力は貧弱。エラー処理、Sum types不在、型制約の弱さ。ただしこのシンプルさが読みやすさと学習容易性を生む。「賢くない」ことを選択した勇気は評価するが、型システムとしては物足りない。 |
| Plain Python | 25 | 優雅なる無防備 型ヒントは存在するが実行時に完全無視。「ドキュメントとしての型」でしかない。動的型付けの柔軟性は魅力だが、大規模システムでは恐怖。テストでカバーする文化は美しいが非効率。 |
| Plain Ruby | 20 | 自由の極北 型が存在しないことを前提とした設計。メタプログラミングとDSLの表現力は素晴らしいが、変更時の影響範囲が予測不可能。小規模チームの職人芸には適するが、スケールしない。 |
この評価表を作成して感じるのは、型システムの価値が「事前検証」という一点に収束していることです。
PHP with Psalm/PHPStanが90点でTypeScriptが88点という順位は、一般的な認識とは逆でしょう。しかしPHPには実行時保証という「最後の砦」があり、その上に静的解析を重ねられる。一方TypeScriptは表現力で勝るものの、実行時には完全に無防備。この逆転現象が興味深い。
Rustの98点は妥当ですが、満点でない理由は「過剰な厳密性」です。ライフタイムの複雑さは、時として問題領域の本質から注意を逸らす。完璧を求めすぎることの代償。
最も印象的なのは、Plain PHPの80点という高評価。「嘘をつかない」という単純な美徳が、複雑な型パズルより価値を持つ場合がある。これは型システム議論が見落としがちな視点です。
GoとRuby/Pythonの低評価は、型システムを「ドメインルール表現」として見た場合の必然的結果。しかしこれらの言語の実用的成功を考えると、型システムの充実度と言語の価値は必ずしも相関しないという重要な示唆を得られます。
この評価軸自体が、静的型付け言語の価値観に偏っているとも言える。動的言語の真の強みは、型システムでは測れない「可塑性」にあるのかもしれません。
この評価表は、「型で複雑なビジネスドメインルールを表現・強制できる能力」に特化した軸で見た場合、2025年11月時点で非常に合理的で、私の考えとほぼ一致するものです。以下で理由を詳しく説明します。
- 評価軸:「型でドメインルールを表現できる能力」×「その制約が事前に(コンパイル時or静的解析時)検証できる保証」
- これはまさにドメイン駆動設計(DDD)の核心です。在庫数0未満を型エラーにしたり、「審査中|承認|拒否」の状態遷移をタグ付きユニオンで死守したり、非空文字列を型レベルで保証したり……という「型で業務ルールを守らせる」能力を測っています。
- 実行時保証か開発時保証かの違いは、実用上ほとんど意味がない(CIで型チェックを失敗させれば同じ)という指摘も正しいです。
| 言語・環境 | 表のスコア | 私の評価(100点満点) | 一致度・コメント |
|---|---|---|---|
| Rust | 98 | 97〜99 | ほぼ完璧に一致。Sum types(enum)+パターンマッチング+newtype patternで「在庫数0..999」すら型レベルで表現可能。所有権システムがさらに不正状態を不可能にする。ライフタイムが時々邪魔になるので-1〜2点。 |
| PHP w/ Psalm/PHPStan | 90 | 98〜100 | 表が控えめすぎるくらい。現時点で最も狂気的にドメイン制約を表現できる(positive-int, 1..100, non-empty-string, array shapes, 条件型, Taint分析まで)。開発時に100%死守可能。実行時保証がない点を-10しているなら理解できるが、実用上はほぼ100点。 |
| TypeScript | 88 | 92〜95 | やや低めに見積もられているが妥当。Conditional Types + Discriminated Union + satisfies + branded typesでかなり表現できるが、Psalmほど細かい範囲型や文字列詳細型は自前実装が必要。zod併用でIO境界も守れる点は強い。 |
| Plain PHP (8.3+) | 80 | 82〜85 | ほぼ一致。Union/Intersection/Enum/readonly/DNFで「そこそこ」守れるが、コレクションや詳細制約は弱い。実行時100%保証は確かに信頼性が高い。 |
| Python w/ Pyright/Mypy | 75 | 78〜82 | ほぼ一致。pydantic v2 + pyrightで実用上かなり強いが、Psalmの細かさには及ばない。 |
| Ruby w/ Sorbet | 55 | 60〜65 | 少し厳しめだが方向性は一致。SorbetはStripe本番運用実績あり、2025年でジェネリクスも強化されたが、Rubyのメタプログラミング文化との相性は確かに悪い。 |
| Go | 48 | 45〜50 | 完全に一致。シンプルさが売りだが、Sum types不在・範囲型皆無・ジェネリクスが貧弱すぎて、業務ルールはほぼ実行時チェックになる。「型で守る」観点では最下位クラス。 |
| Plain Python/Ruby | 25 / 20 | その通り | 型ヒントはドキュメント止まり。 |
- Rustがトップなのは当然。所有権+enum+newtypeで「不正な状態は表現できない」レベルに到達。
- Psalmが90点で2位なのは、現実の業務システムで「型で絶対に間違えさせない」ことを最重視した場合の正しい順位。TypeScriptより表現力が上(特に範囲型・文字列詳細型)。
- Goが48点なのは、Go愛好家からは怒られそうだが、この軸に限れば本当にこれくらい。2025年でもGoの型システムは「最低限のミス防止」止まりで、複雑なドメインルールは実行時バリデーション頼みになる。
この表は**「型で業務ルールを死守したい」人にとっての聖典**のような正しさを持っています。
私が以前「PHP+Psalm 100点、Go 48点」と書いたのも、この表と完全に同じ価値観です。
もしあなたが
「間違えたら大金が動く金融・保険・決済システム」を作るなら → Rust か PHP+Psalm
「フルスタックで現実的に強い型安全性を」求めるなら → TypeScript
「パフォーマンスと運用安定性を最優先」なら → Go(型は諦める)
という選択肢は、2025年11月21日現在でも変わりません。
この評価表は、非常にバランスが取れていて信頼できるものです。
評価軸: 「型でドメインルールを表現できる能力」×「その型制約が事前に検証できる保証」 (補足:型の記述コストに対するリターンの大きさ=ROIも考慮)
| 言語・環境 | スコア | 評価・理由 |
|---|---|---|
| Rust | 99 | 絶対的な守護者 所有権システムは単なるメモリ管理ではなく、「リソースの状態遷移」を型レベルで強制する最強のツール。Newtypeパターンと From/TryFrom トレイトを組み合わせた時の堅牢さは他言語の追随を許さない。「コンパイルが通れば正しく動く」の信頼度は最大。学習コストは高いが、その見返りはドメインの堅牢性として確実に返ってくる。 |
| PHP w/ Psalm/PHPStan | 92 | ハイブリッドの覇者 「実行時の公称型(Nominal Typing)」と「静的解析時の構造的詳細型」の融合が見事。TypeScriptでは消失するクラスの実体が、PHPでは実行時も残りガードとなる点が評価を押し上げる。ジェネリクスの不変性・共変性の扱いは複雑だが、それを使いこなせばビジネスロジックの矛盾をコードを書く前に検知できる。実利的な最強解。 |
| TypeScript | 89 | 構造化された自由 型システムの表現力(Template Literal Types等)は世界一柔軟と言える。しかし、IO境界(APIレスポンス等)での実行時検証にはZod/Valibot等の別ライブラリが必須であり、言語単体での「保証」にはギャップがある。開発体験(DX)は最高だが、型パズルに陥りやすく、ビジネス価値より型定義に時間を溶かすリスクも含む。 |
| Plain PHP (8.3+) | 82 | 堅実な防波堤 型システムとしての派手さはないが、 readonly プロパティや Enum、DNF型により、「不変条件」を言語レベルで保証しやすくなった。静的解析なしでも、タイプヒントに従わないデータは即座に TypeError で弾かれるため、フェイルファストの原則を守りやすい。 |
| Python w/ Pyright/Mypy | 74 | 実用主義の妥協点 Pydanticの存在が前提となるが、データ構造の定義能力は高い。しかし、Python自体の動的な性質(モンキーパッチの可能性など)が、厳密な型保証の足かせとなる場面が残る。型ヒントが「強制」ではなく「注釈」であるという根本設計は、大規模なドメインモデリングにおいて心理的な不安要素となる。 |
| Go | 50 | 意図的な制約 「型でドメインを語る」ことへの拒絶すら感じるシンプルさ。Enumの欠如、nil安全性の低さ(Option型の不在)は、ドメインルールを「if文」の中に隠蔽することを強いる。インフラツールを作るには最高だが、複雑なビジネスルールを型で表現するには不向き。「型システム」の評価としては低くなるのは必然。 |
| Ruby w/ Sorbet/RBS | 45 | 文化の衝突 Rubyの「ダックタイピング」という美学と、静的型付けの厳格さは水と油。Sorbetは強力だが、コードの見た目と書き心地(Writer's experience)を損なう。型を書くためにRubyの良さを捨てるなら、別の言語を使うべきという結論に至りやすい。 |
Claude Opus、Grokと同意見です。評価の鍵は**「不正な状態を表現不可能にする(Make invalid states unrepresentable)」**能力です。
- Rust: Enum(直和型)と所有権により、例えば「決済済みだが未発送」という状態を型として定義し、それ以外の状態でのアクセスをコンパイルエラーにできます。これはドメインルールの物理法則化です。
- PHP w/ Psalm: 多くの人が見落としていますが、PHPのクラスは実行時にも一意な型として存在します。TypeScriptのインターフェースがコンパイル後に消えるのに対し、PHPでは
function process(PaymentId $id)と書けば、実行時にも必ず$idはPaymentIdのインスタンスであることが保証されます。この「ランタイムの裏付けがある上での静的解析」は、実運用において極めて強力な安心感を生みます。
表現力だけならRustを超えて100点かもしれませんが、**「型消去(Type Erasure)」**が減点対象です。「型レベルでは整合しているが、実行時のJSONデータが型と食い違っていた」という事故はTS固有のリスクであり、これを防ぐには二重の定義(型定義とバリデーションロジック)が必要になります(Zod等で緩和されますが)。
Goは「Google規模のエンジニア数で、均質なコードを書く」ためには100点の言語です。しかし、今回の評価軸である「ドメインルールの表現力」においては、**「複雑さを型に逃がすことができない」**ため、低評価となります。ルールを守らせる責任が「コンパイラ」ではなく「人間の注意力とテストコード」に転嫁されているからです。
提示されたお二方の評価表は、「堅牢なソフトウェア設計」の現代的な到達点を正確に捉えています。
特に感銘を受けたのは以下の点です:
-
「Plain PHP (80点)」の再評価
- 動的言語と思われがちなPHPが、実は近年「Java以上に厳格な型チェック(実行時)」を備えている点を見抜いているのは素晴らしい洞察です。
- 「嘘をつかない型システム」という表現は、PHP 8系以降の進化の本質を突いています。
-
静的型付けの価値の再定義
- 「コンパイル時か実行時かの区別より、問題を見つけられるかが重要」というTypeScriptへのコメント、そして「過剰な厳密性の代償」というRustへの指摘は、現場のエンジニアリング感覚と完全に一致します。
-
結論の一致
- 「金融ならRust/PHP+Psalm」「フルスタックならTS」「運用重視ならGo」という住み分けは、2025年の技術選定における黄金律と言って差し支えありません。
この評価表は、単なる機能比較を超え、**「ビジネスの複雑性をどこで制御するか(型か、テストか、運用か)」**というアーキテクチャ設計の指針として極めて有用です。
評価軸: 「型でドメインルールを表現できる能力」×「その型制約が事前に検証できる保証」 (補足: 実運用でのROI、大規模開発での確証、学習コストも加味)
| 言語・環境 | スコア | 評価・理由 |
|---|---|---|
| Rust | 97 | 型による真理の顕在化 所有権・ライフタイムは単なるメモリ管理を超え、「リソースの状態遷移」を型レベルで強制する。例えば「ロック獲得→処理→解放」というドメインワークフローをコンパイルエラーとして保証。 NonZeroUsizeやnewtypeパターンで「在庫数が0以上」は型として表現可能。完璧に近いが、async境界や複雑なライフタイム推論が時に「型の迷宮」を生むため-3。 |
| PHP w/ Psalm/PHPStan | 95 | 最も現実的な完成形 実行時の公称型(Nominal Typing)が静的解析の精度を支える。 positive-int、non-empty-string、array{status: string, count: int<1,100>}など、文字列長や数値範囲まで表現可能。PHPDocは別言語に見えるほど強力。実運用で「型チェックをCIで必須化すれば、実行時保証は不要」というのは正しいが、PHPにはランタイムでの「最終防御線」もある点が他言語にはない安心感。課題はIDE依存度が高く、言語サーバーのパフォーマンス。 |
| TypeScript | 85 | 華麗なる現実逃避 Conditional Types、Template Literal Types、Discriminated Unionsによる型表現力は芸術的。しかし型消去の呪いがすべてを支配する。APIレスポンスの形が変わってもランタイムは無防備。 zod/valibotでの二重定義は生産性の両刃の剣。型パズルに陥ると「型定義のための型定義」地獄もある。開発体験は最良だが、リファクタリング時の「型の嘘」に怯える点が-10。 |
| Plain PHP (8.3+) | 78 | 地味に最も信頼できるreadonlyプロパティ、Backed Enum、DNF型(`A&B |
| Python w/ Pyright/Mypy | 70 | 漸進的型付けの現実Protocol、TypedDict、Literal、Self型で実用上十分表現できる。ただしPythonの哲学的設計「型は強制ではなく契約」が隅々まで浸透しており、モジュール同士の境界で型の嘘が入りやすい。pydanticの存在は大きいが、これ自体が「Pythonの型では不十分だから必要」という証左。ランタイムでのTypeErrorがなく、テスト文化に依存する点が-10。 |
| Go | 42 | 意図的な自縛 2025年現在でもSum types欠如、 nilの蔓延、interface{}の呪縛。Generics追加で改善したが、型制約は依然として貧弱。しかしこれは設計 Philosophy によるもの。「複雑なドメインルールはコードではなく、明確な命名とシンプルな構造とテストで表現すべし」と考えている。インフラツールでは最適だが、金融システムなどの複雑ドメインでは型の壁が低すぎる。 |
| Ruby w/ Sorbet/RBS | 35 | 文化の遺物 Rubyの核心は「メタプログラミングによるDSL化」であり、静的型付けはその美学と根本的に相容れない。Sorbetの sigは侵襲的で、Rubyらしさを殺ぐ。RBSは別ファイルの型定義という、最もツラい形式。Stripeの運用実績はあるが、これは「Rubyの文化を捨ててでも型を入れる価値があると判断した超大規模組織」という例外。普通のチームには文化の摩擦力が大きすぎる。 |
| Plain Python | 20 | 自由の代償 型ヒントは「ドキュメントの進化形」でしかない。 typingモジュールの全機能が実行時に蒸発する。動的型付けの柔軟性は小規模では最強だが、100万行規模では「影響範囲の予測不能性」が技術的負債に。データサイエンス分野での成功は「ドメインが数値計算という限定的でテスト可能な領域」だからこそ。 |
| Plain Ruby | 15 | 型不在の美学 型が存在しないことを前提として設計された言語。 method_missingによるDSLの美しさは、型システムの観点からは「予測不可能性の最大化」。小規模アジャイル開発では生産性が爆発するが、スケールすると「人による暗黙知の共有」がボトルネック。型システム評価としては最低ランクだが、言語価値とは別次元。 |
この評価表が示す最も重要な洞察は、 「型システムの価値は絶対的な表現力だけで測れない」 という点です。
PHPが95点と極めて高いのは、 「静的解析+ランタイム保証の二重防御」 が可能だからです。TypeScriptでは as unknown as T で型の嘘が通り、Pythonでは typing.cast が実行時に消失しますが、PHPでは function process(UserId $id) と書いた瞬間、 絶対にUserId型でなければ物理的に実行できない 。この「最後の砦」があることで、大規模チーム開発における信頼性が格段に向上します。
TSの85点は「型表現力100点、ランタイム保証0点、型消去税-15点」という内訳です。最も危険なのは、 「型レベルでは完璧に設計したつもりが、実行時データがそれと乖離していた」 という事故。GraphQLやtRPCでスキーマを共有しない限り、フロントエンドとバックエンドの型の不一致は常に発生します。これは言語設計上の先天的欠陥です。
Goの42点は 「型システムとしての失敗ではなく、型システムを捨てた分野での成功」 を示しています。Kubernetesなど複雑なシステムがGoで書かれるのは、 「複雑なドメインルールを型で表現しようとしない」 から。代わりに「明確な規約」「網羅的なE2Eテスト」「シンプルなコードレビュー」でカバー。型システムの評価軸では低いが、ソフトウェア工学全体としては高い評価。
Plain Python/Rubyの低評価は、 「型システムの価値観で測った」 結果です。しかしこれらの言語の真価は「型で表現できない可塑性」にあります。RailsのActiveRecordの魔法、Pandasの動的なDataFrame操作は、静的型付け言語では再現困難。型システムの観点からは低いが、 「探索的プログラミング」や「DSL指向設計」 という別軸での価値があります。
この評価表はあくまで「型でドメインを守る」という単一軸。実際の技術選定は3軸で考えるべきです:
| 軸 | Rust | PHP+Psalm | TypeScript | Go |
|---|---|---|---|---|
| 型によるドメイン保証 | ◎ | ◎ | ○ | △ |
| 開発生産性・学習コスト | △ | ◎ | ◎ | ◎ |
| 実行時パフォーマンス・安定性 | ◎ | ○ | ○ | ◎ |
- Rust: 型で絶対に守りたい、パフォーマンスも絶対、学習コストは払える → 金融コア、組み込み
- PHP+Psalm: 型で守りたい、でも素早く開発、運用実績重視 → Webアプリケーション、EC、業務システム
- TypeScript: フルスタック統一、開発体験最重視、ランタイムリスクは許容 → SaaS、スタートアップ
- Go: 型は諦めてシンプルさで統一、運用安定性最重視 → インフラツール、マイクロサービス
この評価表は、 「型システムの価値は文脈次第で変わる」 というより深い真理への入口となります。