-
-
Notifications
You must be signed in to change notification settings - Fork 932
Reuse union class-string sometimes in non-covariant generic #12256
-
I have a custom phpstan-type that I import all over the place to indicate a kind of Test:
/** * @phpstan-type CompareableTestType Test1|Test2|Test3 */ interface CompareableContract { /** @return CompareableTestType */ public function getTest();
I don't want to type those 3 (for now) classes everywhere, so they're a custom type.
I also have a generic UserTest class with template TTestType with a $test property of type TTestType:
$usertest = $user->getLastTest('test1'); // UserTest<Test1> (from custom extension for getLastTest())
Both of those work perfectly separately, but now I want to combine them:
/** * @phpstan-import-type CompareableTestType from CompareableContract */ class TestResult implements CompareableContract { public function __construct( /** @var UserTest<CompareableTestType> */ protected UserTest $usertest, ) {}
Nooo, that's not what I mean! I want $usertest to be a UserTest<Test1>|UserTest<Test2>|UserTest<Test3>, not a UserTest<Test1|Test2|Test3>.
How do I unwrap/ungeneric that correctly in the constructor argument @var? Is that possible? Or should I define the custom type CompareableTestType differently? Is that possible??
(Non-)covariance is killing me! 😆 Not in code/reality, but in Stan.
Beta Was this translation helpful? Give feedback.
All reactions
How do I unwrap/ungeneric that correctly in the constructor argument
To achieve UserTest<Test1>|UserTest<Test2>|UserTest<Test3> instead of UserTest<Test1|Test2|Test3>, I think you need a custom PHPDoc type, something like expand-union<...>.
Replies: 2 comments 2 replies
-
I could make CompareableTestType a real interface, but then phpstan won't know that it's always a Test, because anything could implement an interface.
Is there a way to tell phpstan that I promise that MyInterface is always a Test (abstract)? That helps in other situations too, even though it's very dubious and unwise. There are 10 concrete Test classes, 4 of them are MyInterface, and MyInterface is never used anywhere else, so it's always automatically Test&MyInterface.
Beta Was this translation helpful? Give feedback.
All reactions
-
Is there a way to tell phpstan that I promise that MyInterface is always a Test
Beta Was this translation helpful? Give feedback.
All reactions
-
That doesn't reference exact classes, only the parent. That's probably good, you don't want a circular reference, but it's not what I meant.
Beta Was this translation helpful? Give feedback.
All reactions
-
How do I unwrap/ungeneric that correctly in the constructor argument
To achieve UserTest<Test1>|UserTest<Test2>|UserTest<Test3> instead of UserTest<Test1|Test2|Test3>, I think you need a custom PHPDoc type, something like expand-union<...>.
Beta Was this translation helpful? Give feedback.