Last active
August 30, 2022 04:47
-
-
Save edykim/e97d52ef35d40211fa7188fe582a39b1 to your computer and use it in GitHub Desktop.
a typed collection with phpstan
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php declare(strict_types=1); | |
| interface Spaceship | |
| { | |
| } | |
| interface Car | |
| { | |
| } | |
| interface Animal | |
| { | |
| } | |
| interface Device | |
| { | |
| } | |
| class Camera implements Device | |
| { | |
| } | |
| class SomeCamera extends Camera | |
| { | |
| } | |
| class Cow implements Animal | |
| { | |
| } | |
| /** | |
| * @template T | |
| */ | |
| class Collection | |
| { | |
| /** | |
| * @var T[] $items | |
| */ | |
| protected array $items = []; | |
| /** | |
| * @param T[] $items | |
| */ | |
| public function __construct(array $items) | |
| { | |
| $this->items = $items; | |
| } | |
| /** | |
| * @param int $index | |
| * @return T | |
| */ | |
| public function get(int $index) | |
| { | |
| return $this->items[$index]; | |
| } | |
| } | |
| /** | |
| * @template T | |
| */ | |
| class CollectionGenerator | |
| { | |
| /** | |
| * @param T[] $items | |
| * @return Collection<T> | |
| */ | |
| public function __invoke(array $items) | |
| { | |
| return new Collection($items); | |
| } | |
| } | |
| /** | |
| * @template T | |
| * @param class-string<T> $type | |
| * @return CollectionGenerator<T> | |
| */ | |
| function collectionOf($type): CollectionGenerator | |
| { | |
| /** @var CollectionGenerator<T> $generator */ | |
| $generator = new CollectionGenerator(); | |
| return $generator; | |
| } | |
| /** | |
| * @template TA | |
| * @template TB | |
| * @param class-string<TA> $typeA | |
| * @param class-string<TB> $typeB | |
| * @return class-string<TA>|class-string<TB> | |
| */ | |
| function unionType($typeA, $typeB): string | |
| { | |
| /** @var class-string<TA>|class-string<TB> $empty */ | |
| $empty = ''; | |
| return $empty; | |
| } | |
| function run(): void | |
| { | |
| $arr = [ | |
| new Camera, | |
| new Camera, | |
| new SomeCamera, | |
| new Cow, | |
| ]; | |
| $aCollection = collectionOf(Device::class)($arr); | |
| $bCollection = collectionOf(unionType(Device::class, Cow::class))($arr); | |
| $cCollection = collectionOf( | |
| unionType(Device::class, Spaceship::class), | |
| )($arr); | |
| \PHPStan\dumpType($aCollection); | |
| \PHPStan\dumpType($bCollection); | |
| \PHPStan\dumpType($cCollection); | |
| } | |
| // Line Error | |
| // 109 Parameter #1 $items of callable CollectionGenerator<Device> expects array<Device>, array<int, Camera|Cow> given. | |
| // 115 Parameter #1 $items of callable CollectionGenerator<Device|Spaceship> expects array<Device|Spaceship>, array<int, Camera|Cow> given. | |
| // 117 Dumped type: Collection<Device> | |
| // 118 Dumped type: Collection<Cow|Device> | |
| // 119 Dumped type: Collection<Device|Spaceship> |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Playground: https://phpstan.org/r/d82d8c2c-9e60-4a47-a96f-8da6da453f35