Hacker News new | past | comments | ask | show | jobs | submit login

Regarding the unsoundness-by-default, I wish "--no-implicit-any" was the default but it's really no big thing to just add this flag to any project.



Still... why have type inference in the first place if you can not safely utilize it. The argument for having things unsound is "to strike a balance between correctness and productivity". Having to declare types on everything even if it's just generics beats the productivity argument.


Because turning the inference dial up often results with what Flow does: it shows the error at all the wrong places and doesn't show it at the right one.

Try adding the types to the function in your Flow example. The error will finally move to the last line i.e. Flow will actually become useful in tracing down the error.

http://tryflow.org/#e6512d9c847d504bba8be8b90427ffc3

I think Microsoft made the right call to demand function argument types. It doesn't cost very much at all, but it improves error messages tremendously. It might not matter in a tiny example, but I'd bet that Flow's behaviour can be frustrating in a large project.


Showing a less accurate error is worse than showing no error? How is that "less" frustrating if you have to find a bug? It does not DEMAND the argument type? Adding it to flow also improves the error message? How is that the right call?


Showing a missing type annotation error is better than showing errors at all the wrong places.

Showing no errors is a separate argument entirely, and was addressed by the parent poster (noImplicitAny). I will add that I always use TypeScript with --noImplicitAny which indeed does result with TypeScript DEMANDING type annotations for arguments. Of which you complained:

> Having to declare types on everything even if it's just generics beats the productivity argument.

and to which I respond that

1. its not everything, just function arguments

2. its better to demand function argument types than to show unhelpful error locations.

Implicit any is (was) useful for the early migration phase of the project. At that point you (had to) rename everything from JS to TS to use the compiler, and would get a type error for every unannotated function (which might not be a type error at all). The TS team had to choose between:

1. spending a lot of time and effort to get proper deep unification like Flow's working at acceptable performance in a single-threaded process, even without incremental recompilation, or

2. default to a loose "type checker" and provide a gradual tightening valve for users - at the cost of demanding a bit more annotations: for function arguments (and only if the function is not a part of a single expression or statement where the type can be inferred - e.g. types will be inferred for lambdas passed as function arguments)

(1) may have been worth it if it actually resulted with useful error messages, however as demonstrated above, it often doesn't. So they went with (2), and I'm glad they did - otherwise I'd have to deal with mostly-unannotated TypeScript codebases that produce useless error messages every time you do some sort of refactoring, or enforce type annotations via conventions / code reviews / linters.

Flow's inference is a beautiful marvel of engineering, really, and the type system avoided some legacy TS pitfalls (has safer treatment of nulls, proper union and intersection types from the start) but I'm afraid its not that big of a marvel of practicality.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: