Раньше, чтобы создать nullable ValueObject из nullable примитива, приходилось писать колбасу вроде



null === $stringClientId ? null : ClientId::fromString($stringClientId)
.



Сегодня условные типы Psalm позволяют перенести if в статический конструктор:



/**

* @template T of ?string

* @psalm-param T $id

* @psalm-return (T is null ? null : self)

*/

public static function fromString(?string $id): ?self

{

if (null === $id) {

return null;

}



Assert::uuid($id);



return new self($id);

}



ClientId::fromString($stringClientId)




https://psalm.dev/r/ab0090be4c