psalm: false positive on `InvalidPropertyAssignmentValue`

Hello I came across this issue recently, but unfortunately I was unable to replicate with the online tool at psalm.dev

Consider this example:


final class Bag
{
    /** @var Map<Key, Provider> $providers */
    private Map $providers;

    public function __construct(ProviderA $providerA, ProviderB $providerB)
    {
        $this->providers = mapFromIterable(
            [$providerA, $providerB],
            static fn (mixed $_, Provider $provider) : Pair => new Pair(
                $provider::key(),
                $provider
            ),
        );
    }
}

I’m instantiating Map with a helper function with two instances of Provider, both implementing the Provider interface. Unfortunately psalm reports:

InvalidPropertyAssignmentValue - Bag.php:22:28 - $this->providers with declared type 'Ds\Map<Key, Provider>' cannot be assigned type 'Ds\Map<Key, ProviderA|ProviderB>'

For more details I’m including the internals of mapFromIterable:

/**
 * @param iterable<K, V> $iterable
 * @param callable(K, V): Pair<KReturn, VReturn> $mapper
 *
 * @return Map<KReturn, VReturn>
 *
 * @template K
 * @template V
 * @template KReturn
 * @template VReturn
 */
function mapFromIterable(iterable $iterable, callable $mapper) : Map
{
    /** @var Map<KReturn, VReturn> $map */
    $map = new Map();

    foreach ($iterable as $key => $value) {
        $keyValue = $mapper($key, $value);
        $map->put($keyValue->key, $keyValue->value);
    }

    return $map;
}

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 15 (3 by maintainers)

Most upvoted comments

What are the types of Key and DataSource in your example? Are those interfaces? Classes? What are the relation between the two?

ah sorry, I updated the example, DataSource was supposed to be => Key in the original example/message. I tried to simplify the error for reporting purposes.

In my code I’m using DataSource which is an enum class, so Key here refers to a class used as the Map key.