Now imagine that inputB is directly received from some library you imported. So pyright might not be able to check its type and inputB is actually a List. Then you will never get a crash in the version 1. But its types are wrong as inputB is a List.
The version 2 on the other hand will crash as List don't have a shape attribute. Notice also how func returns inputB, propagating the wrong type.
Sure that means the code still works until you modify version 1, but any developpers or LLM that reads func would get the wrong idea about how to modify such code. Also this example is trivial but it can become much much more complicated of course.
This would not be caught in pyright but beartype would. I'm basically using beartype absolutely everywhere I can and it really made me way more sure of my code.
If you're not convinced I'm super curious about your reasoning!
PS: also try/except in python are extremely slow so figuring out types in advance is always AFAIK a good idea performance wise.
It makes sense I guess mostly if Python doesn't have good third party library typechecking... But how would beartype catch it? I mean a runtime error is a runtime error... You trade one for another?