> I have all the definitions and vars in my REPL and so has my IDE. I get completion on all symbols, I can look at call trees, usages, refactor things with confidence, run functions in isolation, replace them, wrap them, all from the REPL and inside my application
This is great, but it only works if you are executing the code that you want to inspect/complete/refactor. In my experience, that just doesn't scale well.
> You need to do runtime validation.
Type systems don't eliminate this, sure, but when used correctly, they _drastically_ reduce it, which is extremely useful.
> And good luck untangling your type definitions when your requirements change.
That's the best part - the compiler tells me exactly what I have to fix to get things working again. If I do the same thing in a dynamic language, I have to track things down myself, wait for unit tests to fail (hopefully I have 100% coverage...), and pray that there isn't an escape.