An expressive type system allows me to formally specify parts of my system, and have the language itself enforce those constraints. It's much better for me to be able to say:
type Byte is mod 256;
And now any instance of Byte cannot end up larger than 256. In this example, most languages can achieve the same thing as they have an 8-bit unsigned int type. But in Ada I can do this for any arbitrary (positive, I assume, never tried negative) integer after the mod (up the the system's Integer'Last). I don't have to test every time I assign into a variable of this type. I don't have to test after every computation to make sure it's still within the range. It just happens for me. This isn't cheating, this is using my tools to enable me to focus on the overall design and not the menial boilerplate of range checking everything.You're talking about leveraging the type system to help you, but that requires fully liking and understanding the type system, many devs don't understand the type systems they're forced to work with, don't understand how to leverage it, and don't like creating new types. Most devs have a primitive obsession and don't much create their own data types.
To the extent this is true (it requires understanding, but not liking—tolerating enough to actually put the effort into use it well, sure) TDD is no different in this regard, it's just that even with that the best case guarantees it provides are weaker.
What does 'cheating' mean in this context? If anything, type systems (especially modern ones) encourage programmers to think more carefully about the types in their programs.