I try to use the following construction:
/**
* @psalm-template TView as object
* @psalm-param list<Viewable<TView>> $viewables
* @psalm-return list<TView>
*/
function getViews(array $viewables): array
// ...
As you see, here I use nested TView template parameter. The intent is to map list of Viewable objects to their Views, and correctly typehint this. However, psalm gives me an error when trying to use this function. Am I doing something wrong?
see https://psalm.dev/r/d3dfbb95ce
BTW, this works in TypeScript: https://codesandbox.io/s/uwpqw
I suspect that the problem lies in inability of TypeAnalyzer#isAtomicContainedBy() to check TNamedObject against TGenericObject
Yeah! Based on the assumption above I have narrowed down the issue:
https://psalm.dev/r/5006c6f1c6
It isn't related to nested templates now.
Adding -covariant to the template should fix the issue, but template covariance isn't currently inherited.
Here's an adapted version of an existing test that _should_ work, but doesn't: https://psalm.dev/r/e46d450967
@muglug Thank you! Is this -covariant suffix documented anywhere? Also, shouldn't the covariance be the default behaviour?
It's currently undocumented, though it should be. It was added to fix #1603.
Covariance shouldn't be the default behaviour, as covariance comes with its own limitations - namely that covariant generic params can't then be used as input: https://github.com/vimeo/psalm/issues/1609
Thank you for the explanation!
It's currently undocumented
I think there should be an issue dedicated to documenting the template-covariant behavior. If you don't mind, I can create one.
If you don't mind, I can create one.
Yes please! Even better, you could write it! The reason I've resisted is that it's a fairly non-trivial thing to explain.
@muglug Sorry to bother you, after the fix, the original code snippet does still not work https://psalm.dev/r/d3dfbb95ce (even if I add -covariant to the @psalm-template annotation). What did I do wrong in that case?
Similar stuff works in TS: https://codesandbox.io/s/uwpqw
You didn鈥檛 add it in the right place: https://psalm.dev/r/716f4d7159