Supporting templates in utility types #9599
-
I'm building a utility type and I want it to be able to work with generic templates as well as explicit types. I'll use the The extension as written is <?php
namespace MyApp\PHPStan;
use PHPStan\Analyser\NameScope;
use PHPStan\PhpDoc\TypeNodeResolver;
use PHPStan\PhpDoc\TypeNodeResolverAwareExtension;
use PHPStan\PhpDoc\TypeNodeResolverExtension;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
class MyTypeNodeResolverExtension implements TypeNodeResolverExtension, TypeNodeResolverAwareExtension
{
private TypeNodeResolver $typeNodeResolver;
public function setTypeNodeResolver(TypeNodeResolver $typeNodeResolver): void
{
$this->typeNodeResolver = $typeNodeResolver;
}
public function resolve(TypeNode $typeNode, NameScope $nameScope): ?Type
{
if (!$typeNode instanceof GenericTypeNode) {
// returning null means this extension is not interested in this node
return null;
}
$typeName = $typeNode->type;
if ($typeName->name !== 'Pick') {
return null;
}
$arguments = $typeNode->genericTypes;
if (count($arguments) !== 2) {
return null;
}
$arrayType = $this->typeNodeResolver->resolve($arguments[0], $nameScope);
$keysType = $this->typeNodeResolver->resolve($arguments[1], $nameScope);
$constantArrays = $arrayType->getConstantArrays();
if (count($constantArrays) === 0) {
return null;
}
$newTypes = [];
foreach ($constantArrays as $constantArray) {
$newTypeBuilder = ConstantArrayTypeBuilder::createEmpty();
foreach ($constantArray->getKeyTypes() as $i => $keyType) {
if (!$keysType->isSuperTypeOf($keyType)->yes()) {
// eliminate keys that aren't in the Pick type
continue;
}
$valueType = $constantArray->getValueTypes()[$i];
$newTypeBuilder->setOffsetValueType(
$keyType,
$valueType,
$constantArray->isOptionalKey($i),
);
}
$newTypes[] = $newTypeBuilder->getArray();
}
return TypeCombinator::union(...$newTypes);
}
} This allows for doing What I'm wanting to support is being able to use Has anyone got an example of this working they could share, or know where I could look? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Hi, for this use case you need to rework your extension a bit and create It makes the type resolution lazy. It's possible you'll get some BC errors, in that case please report them here and I'll add the necessary |
Beta Was this translation helpful? Give feedback.
Hi, for this use case you need to rework your extension a bit and create
LateResolvableType
. Here's an example: https://github.com/phpstan/phpstan-src/blob/1.11.x/src/Type/KeyOfType.phpIt makes the type resolution lazy.
It's possible you'll get some BC errors, in that case please report them here and I'll add the necessary
@api
.