Psalm: Cannot figure out how to use nested template parameters

Created on 1 Nov 2019  路  9Comments  路  Source: vimeo/psalm

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

bug

All 9 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vudaltsov picture vudaltsov  路  3Comments

greg0ire picture greg0ire  路  3Comments

vudaltsov picture vudaltsov  路  3Comments

orklah picture orklah  路  3Comments

Pierstoval picture Pierstoval  路  3Comments