TypeScript can either sharpen a codebase or create a fog of invented abstractions.
The difference usually comes down to where the effort goes.
Best return on effort
The biggest payoff usually comes from being precise at system edges:
- request and response contracts
- configuration objects
- content schemas
- state transitions with meaningful invariants
Inside smaller implementation details, inference often carries the load well enough.
A practical rule
If a type helps another developer make a safer change later, it is earning its keep.
If a type only exists to impress the current author, it probably is not.