Merging of objects with defined properties should yield objects with union of properties
#2,115 opened on Sep 10, 2019
Repository metrics
- Stars
- (5,369 stars)
- PR merge metrics
- (Avg merge 3d 12h) (5 merged PRs in 30d)
Description
Similar to https://github.com/vimeo/psalm/issues/2105 (declined), so I'm throwing this here for evaluation.
It seems like there's an issue with merging two objects in a declaration like object{foo: string}&object{bar: string}:
<?php
/** @psalm-return object{field1: string}&object{field2: string} */
function combine(object $a, object $b) : object
{
return (object) \array_merge((array) $a, (array) $b);
}
$a = new \stdClass;
$a->field1 = 'a';
$b = new \stdClass;
$b->field2 = 'b';
echo combine($a, $b)->field1;
This reports (https://psalm.dev/r/a0a96475ab):
Psalm output (using commit deb36e8):
INFO: MixedArgument - 15:6 - Argument 1 of echo cannot be mixed, expecting string
If instead of accessing field1 I do access field2, then no errors occur (https://psalm.dev/r/e01ed36829). Maybe only the second declaration in the intersection is taken into account?
Similarly to the above, using generic types A and B and an intersection of A&B leads to inferring mixed (https://psalm.dev/r/76313da9d0):
<?php
/**
* @psalm-template A of object
* @psalm-template B of object
* @psalm-param A $a
* @psalm-param B $b
* @psalm-return A&B
*/
function combine(object $a, object $b) : object
{
return (object) \array_merge((array) $a, (array) $b);
}
$a = new \stdClass;
$a->field1 = 'a';
$b = new \stdClass;
$b->field2 = 'b';
echo combine($a, $b)->field2;
Psalm output (using commit deb36e8):
INFO: MixedArgument - 21:6 - Argument 1 of echo cannot be mixed, expecting string