Do Static Types Make Code Neater?
Static types really are cool. I love static analysis tools, and I really love IDE integrations that help you reduce your cognitive load as a developer, but it’s important to understand that there are tools for JavaScript that provide some of those benefits using type inference. Check out Tern.js for example, which has Atom and Sublime Text integrations and does a pretty impressive job at intellisense. Pair it with JSDoc and it gets even better.
I know lots of people think static types help you prevent bugs, but I’m not aware of any study that proves that static types provide any appreciable reduction in bug density. In fact, there is some evidence that suggests that the additional complexity overhead of static types on a language can actually increase bug density. See “The Broken Promise of Static Types”.
You know what actually does have a big impact on software quality? TDD. TDD can reduce bug density by 40–80% (famously, Springer published research from Microsoft and IBM that showed even more impressive results), and TDD covers a lot of software defects that static type analysis can’t say anything about.
If you’re using both TDD and code reviews (which I believe all software projects should be doing) relatively few type errors ever make it to production. In other words, as a purely QA tool, static types are overrated.
As for the complexity of keeping code structure in your head — class hierarchies are MUCH, MUCH harder to understand than object composition. I should know — I used to write rapid application development tools that helped visually model class designs. When I switched to JavaScript, I stopped using those tools, and significantly reduced my reliance on UML diagrams, etc…
Why? Because all my object relations were flat and understandable at a glance, I simply didn’t need them anymore.
And the flexibility of composition means there’s a lot less maintenance to do in the first place. You simply don’t have the need to refactor class hierarchies because there aren’t any to refactor.
Similarly, functional programming eliminates entire classes of bugs and refactoring work from your software. With pure functions, you don’t have to worry about race conditions, thread locks, etc…
Just because something is different from what you do, and just because it doesn’t integrate as directly with the workflow you use does not make it sloppy.
By the way, if you’re interested in type systems, check out rtype: an effort to build a TypeScript-inspired type system that embraces native JavaScript (instead of building a superset), and the dynamic nature of JS (with runtime checking and reflection).