Types <i>are</i> tests.<p>In a sufficiently strong type system, you can express constraints stronger than &quot;returns a string&quot; or &quot;takes an integer&quot;. For instance, if you want to make sure that a particular function always returns a valid file descriptor, make a structure for file descriptors that just contains a single int, and give it a private constructor that can only be called by the low-level functions that call the actual syscalls, or maybe a public constructor that confirms that the provided integer is actually a file descriptor. Then, as long as your function typechecks, it can only possibly return a valid file descriptor, for <i>all</i> possible inputs.<p>If you take this to an extreme, you get the <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Curry-Howard_correspondence" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Curry-Howard_correspondence</a>, that there&#x27;s a direct mapping between mathematical propositions and types, and between their proofs and functions of the corresponding type. This is what all modern proof assistants build on top of, though their type systems are usually extremely complicated.