diff --git a/src/Psalm/Internal/Type/TypeCombiner.php b/src/Psalm/Internal/Type/TypeCombiner.php index e422f5f23ef..1017b5315f1 100644 --- a/src/Psalm/Internal/Type/TypeCombiner.php +++ b/src/Psalm/Internal/Type/TypeCombiner.php @@ -47,6 +47,7 @@ use Psalm\Type\Atomic\TTraitString; use Psalm\Type\Atomic\TTrue; use Psalm\Type\Union; + use function array_filter; use function array_intersect_key; use function array_keys; @@ -280,7 +281,10 @@ public static function combine( } } - if (!isset($combination->value_types['string'])) { + $has_non_specific_string = isset($combination->value_types['string']) + && get_class($combination->value_types['string']) === Type\Atomic\TString::class; + + if (!$has_non_specific_string) { $object_type = self::combine( array_values($combination->class_string_types), $codebase diff --git a/tests/TypeCombinationTest.php b/tests/TypeCombinationTest.php index 7329d935019..d30593eb863 100644 --- a/tests/TypeCombinationTest.php +++ b/tests/TypeCombinationTest.php @@ -479,6 +479,34 @@ public function providerTestValidTypeCombination(): array 'Exception::class', ], ], + 'combineClassStringWithNumericString' => [ + 'class-string|numeric-string', + [ + 'class-string', + 'numeric-string', + ], + ], + 'combineRefinedClassStringWithNumericString' => [ + 'class-string|numeric-string', + [ + 'class-string', + 'numeric-string', + ], + ], + 'combineClassStringWithTraitString' => [ + 'class-string|trait-string', + [ + 'class-string', + 'trait-string', + ], + ], + 'combineRefinedClassStringWithTraitString' => [ + 'class-string|trait-string', + [ + 'class-string', + 'trait-string', + ], + ], 'combineCallableAndCallableString' => [ 'callable', [