Passing a string where an object was hinted used to be a recoverable fatal, which in practice meant an unrecoverable one. It is an exception now, which makes it testable.
public function testRejectsAnUntypedAmount()
{
$this->expectException(TypeError::class);
(new Invoice())->add('not a Money');
}
That is genuinely useful in a test suite and a trap in application code: catching TypeError around a call to hide a bad argument turns a programming error into a silent branch. Reserve it for boundaries where the input is genuinely untrusted — deserialising a payload, say — and let it propagate everywhere else.