-
Notifications
You must be signed in to change notification settings - Fork 666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for template of template #5788
Comments
I found these snippets: https://psalm.dev/r/0ff07df695<?php
/** @template TCM of object */
interface ClassMetadata {};
/**
* @template T of ClassMetadata
*/
interface ClassMetadataFactory
{
/**
* @template T2 of object
* @psalm-param class-string<T2> $className
* @psalm-return T<T2>
*/
public function getMetadataFor($className);
}
|
Not sure I know enough of ClassMetadata structure, but isn't https://psalm.dev/r/4b0ca83540 good enough? |
I found these snippets: https://psalm.dev/r/4b0ca83540<?php
/** @template TCM of object */
interface ClassMetadata {};
interface ClassMetadataFactory
{
/**
* @template T2 of object
* @psalm-param class-string<T2> $className
* @psalm-return ClassMetadata<T2>
*/
public function getMetadataFor($className);
}
|
Sadly no. My end goal is to let Psalm understand that the ClassMetadataFactory::getMetadataFor returns ORM ClassMetadata, which has a lot of fields not defined in the ClassMetadata defined in Persistence. If I have an entity called user I want to get an |
Well, given that ORM\ClassMetadata is a child of ODM\ClassMetadata, I'd say the contract allows for ORM\ClassMetadata to be returned. I'd say it's up to the caller of the contract to check what kind of ClassMetadata it received. Do you mind explaining the difference between an entity and a document? |
It isn't the ORM and the ODM are 2 different projects, both depend persistence. The former users entities, the later documents. From https://www.doctrine-project.org/projects/doctrine-phpcr-odm/en/latest/reference/introduction.html
That's currently what happens but as long as in the ORM, you expect to be dealing with ORM ClassMetadata. It would be great not to have to do all these assertions. |
Sorry, I confused ODM for persistence. I understand better. How does persistence knows which one it's dealing with? Ideally, when creating the ClassMetadata, we would give it the type correct type as a template |
My plan would be to use |
Oh right, so the end goal would have been something like https://psalm.dev/r/725182085a, but then the error about the template not recognized pops up, right? |
I found these snippets: https://psalm.dev/r/725182085a<?php
namespace Persistence{
/** @template TCM of object */
interface ClassMetadata {};
/**
* @template Type of ClassMetadata
*/
interface ClassMetadataFactory
{
/**
* @template T2 of object
* @psalm-param class-string<T2> $className
* @psalm-return Type<T2>
*/
public function getMetadataFor($className);
}
}
namespace ORM{
/**
* @template TCM of object
* @psalm-extends\Persistence\ClassMetadata<TCM>
*/
interface ClassMetadata extends \Persistence\ClassMetadata{};
}
namespace ODM{
/**
* @template TCM of object
* @psalm-extends\Persistence\ClassMetadata<TCM>
*/
interface ClassMetadata extends \Persistence\ClassMetadata{};
}
|
Yes exactly! |
Doesn't |
I found these snippets: https://psalm.dev/r/61c14d2a53<?php
namespace Persistence {
/** @template TCM of object */
interface ClassMetadata {}
interface AbstractClassMetadataFactory {
/**
* @template TT of object
* @param class-string<TT> $class
* @return ClassMetadata<TT>
*/
public function getMetadataFor(string $class): ClassMetadata;
}
}
namespace ORM {
use Persistence\ClassMetadata as PersistenceMetadata;
use Persistence\AbstractClassMetadataFactory as PersistenceMetadataFactory;
/**
* @template TCM of object
* @extends PersistenceMetadata<TCM>
*/
interface ClassMetadata extends PersistenceMetadata {}
interface ClassMetadataFactory extends PersistenceMetadataFactory {
/**
* @template TT of object
* @param class-string<TT> $class
* @return ClassMetadata<TT>
*/
public function getMetadataFor(string $class): ClassMetadata;
}
}
namespace {
function f(ORM\ClassMetadataFactory $factory): ORM\ClassMetadata {
$r = $factory->getMetadataFor(Exception::class);
/** @psalm-trace $r */;
return $r;
}
}
|
@weirdan it's not an interface, it's a class, and I think it would be more elegant to have |
That seems irrelevant, it'll work the same way with a class.
Why though? Is it to avoid having to specify a docblock for |
It is irrelevant, but I'd thought I would let you know in case you were thinking of some other interface in ORM.
Yes. Note that this method is defined in the abstract class, in persistence, and not overridden in the ORM. I manage to circumvent that by using |
That’s unsafe in a number of ways, I think. It’s a no from me. |
Unless this works in Hack, which I doubt. |
From Hack:
|
Ok, fair enough. |
doctrine/persistence
defines a genericClassMetadata
interface, and its genericClassMetadataFactory
. TemplatingClassMetadataFactory::getMetadataFor()
does not seem possible:https://psalm.dev/r/0ff07df695
I would expect no errors.
The text was updated successfully, but these errors were encountered: