1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Allow coercion from generic array to objectlike with possible keys

This commit is contained in:
Matt Brown 2018-04-04 18:01:53 -04:00
parent 4065fa894f
commit 1282f74931
4 changed files with 24 additions and 16 deletions

View File

@ -350,10 +350,23 @@ class TypeChecker
if ($container_type_part instanceof ObjectLike) {
$generic_container_type_part = $container_type_part->getGenericArrayType();
$container_params_can_be_undefined = (bool) array_reduce(
$container_type_part->properties,
/**
* @param bool $carry
*
* @return bool
*/
function ($carry, Type\Union $item) {
return $carry || $item->possibly_undefined;
},
false
);
if (!$input_type_part instanceof ObjectLike
&& !$input_type_part->type_params[0]->isMixed()
&& !($input_type_part->type_params[1]->isEmpty()
&& $generic_container_type_part->type_params[1]->possibly_undefined)
&& $container_params_can_be_undefined)
) {
$all_types_contain = false;
$type_coerced = true;

View File

@ -141,11 +141,8 @@ class ObjectLike extends \Psalm\Type\Atomic
public function getGenericValueType()
{
$value_type = null;
$any_value_defined = false;
foreach ($this->properties as $property) {
$any_value_defined = $any_value_defined || !$property->possibly_undefined;
if ($value_type === null) {
$value_type = clone $property;
} else {
@ -157,7 +154,7 @@ class ObjectLike extends \Psalm\Type\Atomic
throw new \UnexpectedValueException('$value_type should not be null here');
}
$value_type->possibly_undefined = !$any_value_defined;
$value_type->possibly_undefined = false;
return $value_type;
}
@ -169,7 +166,6 @@ class ObjectLike extends \Psalm\Type\Atomic
{
$key_types = [];
$value_type = null;
$any_value_defined = false;
foreach ($this->properties as $key => $property) {
if (is_int($key)) {
@ -178,8 +174,6 @@ class ObjectLike extends \Psalm\Type\Atomic
$key_types[] = new Type\Atomic\TString();
}
$any_value_defined = $any_value_defined || !$property->possibly_undefined;
if ($value_type === null) {
$value_type = clone $property;
} else {
@ -191,7 +185,7 @@ class ObjectLike extends \Psalm\Type\Atomic
throw new \UnexpectedValueException('$value_type should not be null here');
}
$value_type->possibly_undefined = !$any_value_defined;
$value_type->possibly_undefined = false;
return new TArray([Type::combineTypes($key_types), $value_type]);
}

View File

@ -256,13 +256,6 @@ class TypeCombinationTest extends TestCase
'string',
],
],
'combinePossiblyUndefinedKeysInMultipleArrays' => [
'array{a?:string, b?:int, c?:string, d?:int}',
[
'array{a:string, b?:int}',
'array{c:string, d?:int}',
],
],
];
}

View File

@ -234,6 +234,14 @@ class TypeReconciliationTest extends TestCase
'unionContainsWithstring' => ['string', 'string|false'],
'unionContainsWithFalse' => ['false', 'string|false'],
'objectLikeTypeWithPossiblyUndefinedToGeneric' => [
'array{0:array{a:string}, 1:array{c:string, e:string}}',
'array<int, array<string, string>>'
],
'objectLikeTypeWithPossiblyUndefinedToEmpty' => [
'array<empty, empty>',
'array{a?:string, b?:string}',
],
];
}