[ArrayShape] for maps/associative arrays as dynamic array indexes
Right now if I have following attribute
class Shema {
#[ArrayShape(['string' => Property::class])]
public array $properties;
}
$schema->properties['prop1'] = new Property();
$shcema->properties['prop2'] = new Property();
PHPStorm (PhpStorm 2023.3.4) will report on key Value should be one of: 'string' (why value?).
Is there any way to show possible index values? Like "string" / "int" / "SomeEnum->getValues()"
I think it's worth using native PHP syntax:
/**
* @var array<string, Property>
*/
public array $properties;
// or
/**
* @var array{prop1: Property, prop2: Property}
*/
public array $properties;
// or
/**
* @var array{
* prop1: Property,
* prop2: Property,
* ...<string, Property>
* }
*/
array<string, Property> is not an array shape (based on the concept of array shapes defined by tools like phpstan and psalm that introduced it) but a generic array.
If support is added, it should probably be a separate attribute with a different signature (taking the key type and the value type, not an array describing the shape)
In this case, the 'string' key is a string type (I could write array<non-empty-string, Property> or array<array-key, Property>), so this generalization is valid for autocomplete property to get an array element by the 'string' key, like: $properties['string'].
And since the generic is an unsealed array shape (because does not describe the structure, but only the types), it also allows the Property to be autocompleted from any other keys, like: $properties['prop1'] or $properties['prop2'].
@SerafimArts the whole point of the ArrayShape attribute is to define an array shape, i.e. an array with known keys (and potentially different types per keys). In phpdoc, this is written as array{prop1: PropertyType, prop2: PropertyType} (notice the { } vs < > for a generic array).
A generic array is not the equivalent of an unsealed array shape.
Your example #[ArrayShape(['string' => Property::class])] in the issue description has already a proper meaning, which is the type array{string: Property} (i.e. an array with a string key, not an array with a key being any string)