I love manifest typing.Manifest typing means that you actually write down the types you expect parts of your code to be -- be it local variables, members, parameters or return values. Quite often this is referred to as "static typing", although the latter includes other forms such as type inference or structural typing.
Why do I love manifest typing? Because it lets me express what I want right in place and I think that is unique to manifest typing. There are other advantages it shares with static typing in general such as certain types of tool support, but only manifest typing allows me to write down what I think should be true.
That step of writing down my expectations is extremely important for me. Not doing so seems to make my code brittle: if the type of whatever I'm currently looking at changes over time it might cause problems with further assumptions I made at the time of writing. Even if type inference ensures that the compiler will detect certain incompatibilities, I somehow still prefer to be told about that change so I can vet it. After all I might know about further assumptions I made that the compiler does not know about.
It's even worse if I have to rely on tests. While I do believe that tests are a valuable tool, I think people who think they replace specifications are dangerous. A specification is inherently all-quantified, i.e. what is specified has to be true in any case. As opposed to that a test is always existentially quantified, i.e. it tests only particular instances. Maybe you get all the interesting cases, maybe you don't. Code coverage tools can help, but taking that to the extreme just doesn't seem easier than specifying what you want in the first place. If I can make a hard rule I prefer that over listing example cases, only those aspects that I can't specify I'll test.
My problem with modern programming languages is not that they force me to write down my expectations, my problem is that their language is not expressive enough (and sometimes as in the case of Java also broken). Add into that a culture of being happy to ignore basic principles of specifications (e.g. the JDK is happy in multiple places to let subtypes break the specification of their supertypes) and you get a big mess. But my answer to this mess is not to forget about the idea, it is to try again and hopefully get it right next time.
To make manifest typing really useful it should be expressive enough that it documents expectations and promises quite clearly. This is a core notion in the Design by Contract approach and I think while Eiffel didn't take off there is a lot to learn there. There's also the expressivity you find in XML Schema Part 2 with the language of restrictions offered on the types (which are value types). Just imagine how much validation code gets unnecessary if you would have that type of expressivity in the language.
In fact any validation code is nothing but an additional type system on top of what your language offers, which seems to be an indication of how weak our programming languages are. You can not even express the contents of a basic user registration form in the type system of any programming language I know. I consider that as a big shortcoming, since there is clearly a need for those type of specifications on every single tier in our architectures.
And to round things off: I also love manifest typing (and in this case static typing in general) because it allows me to forget about certain details of my code. In a way my brain is always full -- like the Linux kernel I try to use every last bit for something useful. Having to remember types of variables (or even worse: parameter and return values) takes space that could be used for thinking about the conceptual model, the data flow in my program, the overall architecture or a hundred other things that are more interesting than that type information. Let my IDE handle this for me and let it do in a way that I can be sure I don't have to care unless I want to.