Psalm: Constants annotations do not work.

Created on 18 Feb 2020  路  8Comments  路  Source: vimeo/psalm

Most helpful comment

Howdy,

we saw that issue being closed without any feedback. Is there any reason why this is closed?

As far as i can see, in list<> class constants are working as array-value. But in array{} they are not working as array-key. Is there any reason why this is not supported?

Test cases: https://psalm.dev/r/e80ed1b65b

All 8 comments

I found these snippets:


https://psalm.dev/r/d7e2009c63

<?php

class A {
    private const KEY_PARTITION = 'process_name';
    private const KEY_SORT = 'id';

    /**
     * @return string[]
     *
     * @psalm-return array{self::KEY_PARTITION: string, self::KEY_SORT:string}
     */
    private function constructKey(string $partitionKey, string $sortKey): array
    {
        return [
            self::KEY_PARTITION => $partitionKey,
            self::KEY_SORT      => $sortKey,
        ];
    }
}
Psalm output (using commit 6e80887):

ERROR: InvalidReturnStatement - 14:16 - The type 'array{id: string, process_name: string}' does not match the declared return type 'array{A::KEY_PARTITION: string, A::KEY_SORT: string}' for A::constructKey

ERROR: InvalidReturnType - 10:22 - The declared return type 'array{A::KEY_PARTITION: string, A::KEY_SORT: string}' for A::constructKey is incorrect, got 'array{id: string, process_name: string}'

Only string keys work in that context: https://psalm.dev/r/a960775fb7

I found these snippets:


https://psalm.dev/r/a960775fb7

<?php

class A {
    private const KEY_PARTITION = 'process_name';
    private const KEY_SORT = 'id';

    /**
     * @return string[]
     *
     * @psalm-return array{process_name: string, id:string}
     */
    private function constructKey(string $partitionKey, string $sortKey): array
    {
        return [
            self::KEY_PARTITION => $partitionKey,
            self::KEY_SORT      => $sortKey,
        ];
    }
}
Psalm output (using commit 6e80887):

No issues!

Howdy,

we saw that issue being closed without any feedback. Is there any reason why this is closed?

As far as i can see, in list<> class constants are working as array-value. But in array{} they are not working as array-key. Is there any reason why this is not supported?

Test cases: https://psalm.dev/r/e80ed1b65b

I found these snippets:


https://psalm.dev/r/e80ed1b65b

<?php

class Foo {
    public const MY_KEY = 'x';
}

/**
 * A class constant as list array-value does work and is resolved
 *
 * @return list<Foo::MY_KEY>
 */
function test__success1(): array {
    return [Foo::MY_KEY];
}
/**
 * ...even with "wildcard".
 *
 * @return list<Foo::MY_*>
 */
function test__success2(): array {
    return [Foo::MY_KEY];
}
/**
 * A class constant as array-key with "optional" works
 *
 * @return array{Foo::MY_KEY?:string}
 */
function test__success3(): array {
    return [Foo::MY_KEY => 'foo'];   
}
/**
 * ...but an multidimensional array with class constant as array-key required not work.
 * 
 * @return array{Foo::MY_KEY:string}
 */
function test__fails1(): array {
    return [Foo::MY_KEY => 'foo'];
}
/**
 * Same for wildcard class constant as array-key
 *
 * @return array{Foo::MY_*:string}
 */
function test__fails2(): array {
    return [Foo::MY_KEY => 'foo']; 
}
Psalm output (using commit 013467d):

ERROR: InvalidReturnStatement - 37:12 - The inferred type 'array{x: string(foo)}' does not match the declared return type 'array{Foo::MY_KEY: string}' for test__fails1

ERROR: InvalidReturnType - 34:12 - The declared return type 'array{Foo::MY_KEY: string}' for test__fails1 is incorrect, got 'array{x: string(foo)}'

ERROR: InvalidReturnStatement - 45:12 - The inferred type 'array{x: string(foo)}' does not match the declared return type 'array{Foo::MY_*: string}' for test__fails2

ERROR: InvalidReturnType - 42:12 - The declared return type 'array{Foo::MY_*: string}' for test__fails2 is incorrect, got 'array{x: string(foo)}'

I find myself often using constants as array key because that's the only way to have IDE auto-complete and avoid typo. Having to resort to hardcoded strings in annotations completely defeats that purpose.

The point of array{...} annotations is conciseness. If instead Psalm has to worry about all the indirection that class constants provide, a lot of the ergonomics of object-like types disappear from an internal perspective.

I've now made the error more explicit

Was this page helpful?
0 / 5 - 0 ratings