An IDE can assist you even better when it can understand the code you're writing. For example, autocomplete "myString.re" without type hints, and an IDE like IntelliJ might suggest the method "reject()" (which is found on a Promise interface), or "remove()" (which is found on a DB entity interface), as well as "replace()" (which is found on a String interface). Wouldn't it be nice for it to always pick the right option?
TypeScript doesn't help with immutability at all. For that, you should look at something like PureScript. (Or GHCJS, or any other compile-to-JS languages that support immutability.) TypeScript assumes you are sticking with JavaScript's semantics, mutability and all. If you want immutability, you still need to use "Object.freeze()". Variable mutation is not something picked up by types alone.
There are other languages that introduce "dependent types", which can actually include values in their type signatures, which might be able to specify something like you want; i.e. "a function that accepts an argument of type 'a' which derives a number, and returns the same type 'a', but the returned value must be equal to the input value plus 10".
Documentation is nice... or so I've heard! Speaking for myself, developers are lazy and just want to write code. Why not make them document the code as they write it? Plus, external documentation (even as JavaDoc-style comments) always falls out of date with the code.
I think better than tests, is to enforce "design by contract" - assert your preconditions and postconditions on every function. This inlines your assumptions and behaviour verification with the actual code to be run. (If performance is a concern, you can implement this in a way that allows you to disable assertions.)
In general, the more guarantees you can enforce at compile time (such as only accepting certain types of values, or that input values are never mutated in place), the less need there is for having twice as much testing code as application code.