How to resolve Pslam MixedReturnTypeCoersion

350 views Asked by At
ERROR: MixedReturnTypeCoercion - src/Entity/User.php:98:16 - The type 'non-empty-array<array-key, "ROLE_USER"|mixed>' is more general than the declared return type 'array<array-key, string>' for App\Entity\User::getRoles (see https://psalm.dev/197)
        return array_unique($roles);

I am running psalm in a symfony project and getting the above Error, below is the method definition but I have no idea what to adjust in order to fix the error.

/**
     * @see UserInterface
     * @psalm-return array<array-key, string>
     * @return string[]
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }
2

There are 2 answers

0
Biapy On BEST ANSWER

here are two solutions to this issue. It is an implementation of orklah answer.

The first solution is to declare array_unique() return value as an array of string:

    /** 
     * @see UserInterface
     *
     * @return string[]
     * @psalm-return array<array-key, string>
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        /** @psalm-var array<array-key, string> $roles */
        $roles = array_unique($roles);

        return $roles;
    }

Please note that Psalm allows the use of list<string> for string[]. list is an array<int, string> which first key is 0 :

    /** 
     * @see UserInterface
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        /** @psalm-var list<string> $roles */
        $roles = array_unique($roles);

        return $roles;
    }

The second solution is more of a work-around: suppress the warning.

    /**
     * @see UserInterface
     *
     * @return string[]
     * @psalm-return array<array-key, string>
     *
     * @psalm-suppress MixedReturnTypeCoercion
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }
0
orklah On

What Psalm is trying to tell you, is that it can't check that $this->roles has only string elements. You need to either check that inside your function or add some phpdoc above that property to say that it can only contains strings