vimeo/psalm

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

Open

#2,115 创建于 2019年9月10日

在 GitHub 查看
 (3 评论) (0 反应) (1 负责人)PHP (668 fork)batch import
Help wantedenhancement

仓库指标

Star
 (5,369 star)
PR 合并指标
 (平均合并 3天 12小时) (30 天内合并 5 个 PR)

描述

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

贡献者指南