|
|
|
|
|
by jupp0r
808 days ago
|
|
For me it makes sense to distinguish between type inference at the call site or the definition site. As a caller of a function, I don't want to have to spell out type parameters for that function if they can be inferred (but forcing inference is also not great because it's helpful to have type parameters that have nothing to do with the inputs and merely depend on the outputs). At the definition site, I agree with the author that type inference is more of a burden for the most part, at least if the function is more than a hidden implementation detail of the class/module/file. |
|
Bidirectional type checking kinda sorts this out by requiring annotations on top level functions and inferring or checking the rest in a mechanical manner. That's kind of a sweet spot or me. (And reportedly it's faster and gives better error messages.) Most dependent typed languages do this. I believe out of necessity. And Typescript also requires top level function definitions, but I haven't cheked if it is using the bidirectional algorithm.
If that's what the author is trying to say, then I agree. And with a Hindey-Milner system it's still best to annotate (most of) your top level functions (IMHO).
And I've gotten into trouble not doing this in the past. I started a project at work with flowjs, got inscrutable type errors in a different file than wherever the root cause was and bailed for typescript. In hindsight, it wasn't the fault of flowjs, but rather my lack of annotations on top level functions. (I knew far less about type-checking at the time.)