vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.54k stars 660 forks source link

[Enhancement] map type for keyed arrays that have identical values #9986

Open kkmuffme opened 1 year ago

kkmuffme commented 1 year ago

Unlike typescript where Record<'foo'|'bar', string> means every key has a value of string, psalm treats this as or. Currently only array{foo: string, bar: string} is possible to tell psalm that ALL these keys exist with string. This is a problem for a) big arrays that have all the same type (e.g. shipping information) where it's hard to read/lots of boilerplate docs b) does not allow to modify array values but keep the keys the same when using templates, e.g. https://github.com/vimeo/psalm/issues/5994 or https://psalm.dev/r/c39fbb3124

A new map type like map<'foo'|'bar', string> or alternatively (to keep it consistent with typescript) record<'foo'|'bar', string> would resolve this issue.

Since there is already a class-string-map type in psalm, I guess this isn't too far fetched.

Essentially, this new type extends keyed array where all types are identical and all keys are non-optional.

Feedback and suggestions please :-)

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/c39fbb3124 ```php $a * @psalm-return array */ function takesAnInt($a) { foreach ( $a as $key => $value ) { $a[ $key ] = 'hello' . $value; } return $a; } $x = takesAnInt( array( 10 => 'bar', 15 => 'world' ) ); /** @psalm-trace $x */; ``` ``` Psalm output (using commit 8d1876a): INFO: Trace - 17:23 - $x: array<10|15, string> INFO: UnusedVariable - 16:1 - $x is never referenced or the value is not used ```