I think we can categorize people who use PEP 484 types into broadly two groups: people who use types from the start on new codebases, and people who want to start adding types to an existing (and often large) codebase. Typing tries to accommodate both groups, which means there'll sometimes be features that are more useful for one group than another.
For example, I think TypedDict is one example of a construct that's particularly useful for people trying to add type hints to existing code bases. For better or for worse, some of these kinds of codebases really like using dicts instead of objects to pass around data, which means it'll sometimes be easier to type the dicts instead of migrating everything in one shot to use objects. Typing (and mypy) tries to make it easy to make these sorts of incremental changes.
I also want to point out that casting isn't necessarily a bad thing: PEP 484 is designed to be a gradual type system and lets you pick and chose to what degree you want to validate vs trust incoming external data. You can do anything between defining a full (or partial) schema for incoming data and validating + deserializing it into objects using something like Pydantic to just trusting that the input is stable and using a cast. (The latter option would be less ceremony -- and if the input data is large, let you skip a potentially expensive validation/deserialization step).
But regardless of whether you choose to trust vs verify, it's still useful if the type checkers and IDEs can help you *use* the data correctly, as Dustin said. So, TypedDicts.
-- Michael