Last active
August 20, 2025 17:31
-
-
Save ruudk/efcb19b114b8254d1733038cddc9edf6 to your computer and use it in GitHub Desktop.
Generics issues with PHPStorm
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); | |
// composer require webonyx/graphql-php | |
use GraphQL\Language\AST\DirectiveNode; | |
use GraphQL\Language\AST\FieldNode; | |
use GraphQL\Language\AST\NodeList; | |
include __DIR__ . '/vendor/autoload.php'; | |
/** | |
* @var NodeList<DirectiveNode> $list | |
*/ | |
$list = new NodeList([ | |
new DirectiveNode([]) | |
]); | |
foreach ($list as $item) { | |
// this works, PHPStorm understands $item is DirectiveNode | |
echo $item::class . PHP_EOL; | |
} | |
// But now we do this: | |
$fieldNode = new FieldNode([ | |
'directives' => new NodeList([ | |
new DirectiveNode([]) | |
]) | |
]); | |
foreach ($fieldNode->directives as $item) { | |
// PHPStorm thinks $item is mixed | |
echo $item::class . PHP_EOL; | |
} |
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); | |
include __DIR__ . '/vendor/autoload.php'; | |
final class ChunkedIterator | |
{ | |
/** | |
* @template TKey of array-key | |
* @template TValue of mixed | |
* | |
* @param Iterator<TKey, TValue> $iterable | |
* | |
* @return Generator<int, non-empty-array<TKey, TValue>> | |
*/ | |
public static function chunk(Iterator $iterable, int $chunkSize) : Generator | |
{ | |
$chunk = []; | |
for ($i = 0; $iterable->valid(); ++$i) { | |
$chunk[$iterable->key()] = $iterable->current(); | |
if (count($chunk) === $chunkSize) { | |
yield $chunk; | |
$chunk = []; | |
} | |
$iterable->next(); | |
} | |
if ($chunk !== []) { | |
yield $chunk; | |
} | |
} | |
} | |
/** | |
* @return Generator<int, array{id: int}> | |
*/ | |
function generator() : Generator | |
{ | |
for ($i = 0; $i < 13; ++$i) { | |
yield ['id' => $i]; | |
} | |
} | |
$iterator = ChunkedIterator::chunk(generator(), 3); | |
// \PHPStan\dumpType($iterator); | |
// Dumped type: Generator<int, non-empty-array<int, array{id: int}>, mixed, mixed> | |
foreach ($iterator as $chunk) { | |
// \PHPStan\dumpType($chunk); | |
// Dumped type: non-empty-array<int, array{id: int}> | |
// But PHPStorm thinks $chunk is $2|array|mixed | |
foreach ($chunk as $item) { | |
// \PHPStan\dumpType($item); | |
// Dumped type: array{id: int} | |
// But PHPStorm thinks $item is array|Generator | |
echo $item['id'] . PHP_EOL; | |
} | |
echo "Flush...\n"; | |
} |
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); | |
include __DIR__ . '/vendor/autoload.php'; | |
// composer require symfony/type-info | |
use Symfony\Component\TypeInfo\Type; | |
/** | |
* @template T of Type = Type | |
*/ | |
interface TypeInitializer | |
{ | |
/** | |
* @param T $type | |
*/ | |
public function initialize(Type $type) : void; | |
} | |
/** | |
* @implements TypeInitializer<Type\ObjectType<*>> | |
*/ | |
final class ObjectTypeInitializer implements TypeInitializer | |
{ | |
#[Override] | |
public function initialize(Type $type) : void | |
{ | |
// \PHPStan\dumpType($type); | |
// Dumped type: Symfony\Component\TypeInfo\Type\ObjectType<*> | |
// PHPStorm thinks $type is just a Type | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment