I can't count the number of times I've seen None-related errors in prod because some function deep in the business logic can't handle a None parameter.
Another huge benefit of type annotations is that it adds friction for clever code. As I've retroactively added type annotations to old code, I've discovered wild polymorphism. Some functions required upwards of 10 type signature overloads to account for all the polymorphism -- engineers have to remember all that polymorphism! Engineers won't write extremely polymorphic functions if they also have to write the convoluted overloads.
As long as your definition of "just works" is "run, crash, fix something, run, repeat". I remember the pre-type-annotation days, and still live it with some libraries. I find it quite unpleasant, but hey I guess some folks like the "freedom".
> So it's very easy to create code that passes the type checker, but fails at runtime or vice versa.
In theory, yes, in practice, not as much as you might think. If you actually use mypy with strict, which is actually really hard to do, you will find very, very few surprises.
> As long as you’re validating inputs then you don’t need type validation at runtime.
The issue is that type validation is done by a different tool, that follow similar, but not identical rules to the runtime. So it's very easy to create code that passes the type checker, but fails at runtime or vice versa. Type validation is something Python should be able to do itself, it's part of the language after all.