Removing a type hint in a child class used to be a fatal error, which meant an interface written with a concrete type could never be relaxed without breaking every implementation at once.
interface Handler
{
public function handle(Request $request);
}
class LegacyHandler implements Handler
{
// omitting the type is now allowed — it is wider, not narrower
public function handle($request)
{
return $this->dispatch($request);
}
}
The rule follows from substitutability: a child may accept more than its parent promised, because anything valid for the parent is still valid here. It may not accept less. In practice this is a migration tool rather than a design one — it lets an interface add a type hint that implementations adopt one at a time, which is the difference between a change you can ship and one you cannot.