PHPのジェネリクス型超入門!

php ジェネリクス PHP
この記事は約6分で読めます。

この記事の最終更新日: 2025年5月9日

php ジェネリクス

PHPはバージョン8.1以降、言語レベルではネイティブなGenericsをサポートしていませんが、DocBlockアノテーションを通じてPHPStanPsalmといった静的解析ツールがGenerics型を解釈し、型安全性を大幅に向上させています。さらにRFC「Generic Types and Functions」提案によって、将来的なネイティブサポートの実現にも期待が集まっています。本記事では、現状のDocBlockベースの使い方から静的解析ツール別の設定、将来展望までを網羅的に解説します。


1. PHPにおけるGenericsの概念とRFC提案

PHPの公式仕様にはGenericsが実装されていませんが、RFC「Generic Types and Functions」では、Collection<T>のようなジェネリック型を言語機能として導入する案が提示されています。これにより、エンティティごとにコレクションクラスを作成する手間を省き、重複コードを削減できます。

DocBlockレベルでは、@templateタグを用いて型パラメータを定義し、@param T[] $array@return T|nullで型情報を明示する運用が主流です。これを静的解析ツールが解釈することで、実行時に近い型安全を確保できます。


2. DocBlockベースのジェネリクス仕様

2.1 基本パターン

/**
 * @template T
 * @param T[] $array
 * @return T|null
 */
function first(array $array) {
    return $array[0] ?? null;
}

上記の宣言により、first([1,2,3])int|nullfirst(["a","b"])string|nullとして扱われます。

2.2 制約付きGenerics(Upper Bounds)

特定の型を継承・実装したオブジェクトのみを受け付けたい場合、ofキーワードで上限制約を設定できます。以下はExceptionのサブクラスに限定する例です。

/**
 * @template T of \Exception
 * @param T $exception
 * @return T
 */
function wrapException($exception) {
    return $exception;
}

2.3 共変・反変(Variance)

ジェネリクスの共変性を@template-covariant、反変性を@template-contravariantで指定し、APIの柔軟性を高めることが可能です。

/**
 * @template-covariant T
 */
interface Collection {}


3. PHPStanでのGenericsサポート

PHPStanはGenericsに関する設定が豊富です。

  • @template / @phpstan-templateで型パラメータを宣言可能
  • エラー無視設定:generics.notGenericmissingType.genericsignoreErrorsで抑制
parameters:
  ignoreErrors:
    - '#generics\.notGeneric#'


4. PsalmでのGenericsサポート

Psalmでは@psalm-templateタグを活用し、より細かな型制御が可能です。

/**
 * @template T
 * @psalm-param T $value
 * @psalm-return T
 */
function mirror($value) {
    return $value;
}


5. Iterable型・ユーティリティ型との組み合わせ

DocBlockでは、イテラブルやマップ型のキー・値を型安全に扱う記法が用意されています。

/** @var iterable&lt;string, User> $usersById */

PHPStanではCollection<int, Type>のようにジェネリックなコレクションを記述可能です。


6. 現状と将来展望

DocBlockベースのGenericsは現場で広く活用されていますが、あくまで静的解析ツール依存です。The PHP Foundationのレポートでは、Javaに近いDocBlockGenericsの利点と、ランタイム影響がない制約が指摘されています。

Generics導入によるエンジン負荷とコミュニティ要望のバランスは今後の課題として議論中です。


7. ベストプラクティス

  1. DocBlockで必ず型パラメータを定義する。
  2. 上限制約(of)で安全性を強化する。
  3. 共変(@template-covariant)/反変(@template-contravariant)の適切な設定。
  4. エラー無視は最終手段として利用。
  5. RFC提案動向をウォッチし、将来的な言語機能対応を見据える。

8. まとめ

現状のPHPでは、DocBlockアノテーションを通じたGenericsサポートが最前線です。PHPStanやPsalmの設定を使いこなし、コードの型安全性と可読性を両立させましょう。将来のネイティブGenerics実装にも備え、ジェネリクス設計を積極的に取り入れてください。


出典

クリックしたら、
楽天モバイル大盤振る舞いのキャンペーン中らしいです (本ブログ管理人は楽天モバイル2台持ちです) 楽天モバイル
PHP
daigoroをフォローする

コメント

タイトルとURLをコピーしました