vimeo/psalm

Merging of objects with defined properties should yield objects with union of properties

Open

#2 115 ouverte le 10 sept. 2019

Voir sur GitHub
 (3 commentaires) (0 réactions) (1 assigné)PHP (668 forks)batch import
Help wantedenhancement

Métriques du dépôt

Stars
 (5 369 stars)
Métriques de merge PR
 (Merge moyen 3j 12h) (5 PRs mergées en 30 j)

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

Guide contributeur