Unless you can exhaustively check your function for its whole domain, you really can't . Your function could indeed return pink elephants when passed unicorns.
> Unless you can exhaustively check your function for its whole domain, you really can't.
If I generate values within a function that are arguments to a constructor call, and the make the constructor call and return the result with no further manipulation, I can—without exhaustive, or even any—testing be quite confident that the function will return the type for which the constructor so called is the constructor any time it returns, and fail otherwise.
> and return the result with no further manipulation, I can—without exhaustive, or even any—testing be quite confident
But when you start having loops, conditions, arrays, nullable references etc. you can't be so confident any more unlike with proper type checking where you can be fully confident.
right, but it is not the unit test that is giving you that confidence and the unit test will not help you if the function is later modified.
What you have, after manual inspection of the code, is some sort of informal and not written down correctness proof. A machine tested proof would be better and types help with that.