new型
型名ではない文字列からオブジェクトを生成するためのPHPStanの型。PHPStan 1.11で導入される。 GitHub
Ondřejによる告知
基本的な使い方
最少の使い方の例を示す
code:php
/**
* @template TName of string
* @param TName $id
* @return (TName is class-string ? new<TName> : mixed)
*/
function get1(string $id): mixed
↑ のコードは文字列型からオブジェクトに変換できることを示している
newという型名だが、これは新しく作られるインスタンスという意味ではない
もとはobject<T>として提案されたが、
これだけの例ならば、従来の機能ではもっと短く書くこともできる
code:php
/**
* @template T
* @return ($id is class-string<T> ? T : mixed)
*/
function get2(string $id): mixed
つまりnew型の本質は型を短いコードで書くことではない
どんなときに嬉しいのか
次のようにクラス名ではない文字列でオブジェクトを生成したいとする。
code:php
$user = get('user'); // => App\User
$book = get('book'); // => App\Book
code:php
/** @return ($id is 'user' ? User : ($id is 'book' ? Book : never)) */
function get(string $id): object {
return match($id) {
'user' => new User(),
'book' => new Book(),
default => throw new \LogicException('Unexpected $id'),
};
}
assertType('App\User', get('user'));
assertType('App\Book', get('book'));
条件付き戻り値型 ($id is 'user' ? User : ($id is 'book' ? Book : never))
なんかかったるい
増やすの大変
new型を使うとこう書ける
code:php
const MAP = [
'user' => User::class,
'book' => Book::class,
];
/**
* @template T of key-of<MAP>
* @param T $id
*/
function get(string $id): object {
// ...
DIコンテナの型付け
さらに役立つのはDIコンテナのような型付けですね
べんり!
ただ、このTMapをアプリケーションまでどうやって伝えるのか… 読者への課題とします (丸投げ)