This diatribe is actually a fantastic argument for Typescript. Type annotations do exactly what you're talking about, except they also have an enforcement mechanism in the compiler and, using good tools, they travel with the code. So if you've passed a reference to a function somewhere, Typescript still knows what its legal arguments and return values are. If you've passed in an object that came from a function that declared its return type, then you know that you can't pass a property it doesn't have to something else that won't accept an undefined. And, with proper tools, you know all that just by hovering your cursor over the variable or function--no need to jump around and read comments elsewhere.