Ironically, I find having types allows me to reason more about an app in isolation. Pick any function in isolation with a typed language and I know the shape/contents of the data I'm dealing with. I know what these things "are". With something like Clojure and no Spec, I have no idea what I'm dealing with until I find the source of where the original data came from. Having worked on an application that used a Clojure library that read sql from a file and translated the queries into maps, I had to look at the sql file every time to make sure I had the data I thought I did. In my experience, worrying about what could be changing the data is overrated. In a typed language, I know exactly what's changing the data since I can statically guarantee what other parts of the codebase are mutating it. It can definitely become a problem with concurrent code, but that happens so rarely in the codebases I've worked on that isn't really a concern and there are ways to mitigate it when it is.