Hacker News new | comments | show | ask | jobs | submit login
Exploring Flow, Facebook's Type Checker for JavaScript (crmarsh.com)
65 points by frostmatthew 845 days ago | hide | past | web | 20 comments | favorite

Here's a quick link to the project page itself: http://flowtype.org/

What is the difference between recently announced Flow and TypeScript? http://www.reddit.com/r/javascript/comments/2mrngf/what_is_t...

After spending a few minutes bouncing around to other discussions trying to figure this out, the answer seems to be something like "Use Flow if you: 1) use JSX, or 2) can't be bothered to annotate your code but want a chance of maybe catching some classes of error anyway."

Regarding #1, I don't personally like JSX, but a lot of people do, so maybe they should use Flow. It seems likely the TypeScript compiler would barf on code that employs JSX.

Regarding #2, I can't see how that will drive any appreciable adoption of this tool. If you care enough to statically analyze your code, you probably care enough to annotate it to get the much stronger safety guarantees that will provide (not to mention other benefits, like "free" self-documentation, and enabling more sophisticated tooling, that have been discussed elsewhere at length).

Maybe I've missed an important use case here, but that's what I've been able to piece together since I skimmed the article. And since the author was recently interning on a large React codebase and never mentions TypeScript in the article, I have a feeling he falls into use case #1 above.

I mean you seem to discredit "incrementally adding annotations" as a feature.

You're correct that anyone that would like to statically analyze a part of their code would want all of it analyzed. However, you're totally disregarding the biggest problem. Large existing code bases.

I'm not sure if you've ever had to deal with a large, deployed to production code base, but it doesn't seem like you have. I can tell you there is no way to refactor all of it at once.

The only realistic way forward is to refactor a single function, perhaps full file, one at a time.

Like skybrian's reply mentioned, I don't think this is actually an area where Flow is much stronger than TypeScript, if at all. AFAIK, virtually all vanilla JavaScript should also readily compile as TypeScript.

In my mind the difference is that TypeScript doesn't purport to analyze the correctness of regions of code that lack type annotations. Meanwhile, Facebook claims that "Flow understands the control flow through the program."[0] That's great in theory, and maybe their control flow analysis is really quite sophisticated, but ultimately isn't this isomorphic to the halting problem?

[0]: https://code.facebook.com/posts/1505962329687926/flow-a-new-...

> ...TypeScript doesn't purport to analyze the correctness of regions of code that lack type annotations.

TypeScript infers the types of local variables. For example, the following unannotated code would cause the TypeScript type checker to fail:

    // error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
    [1, 2, 3].join(4);
However, even when the TypeScript typechecker fails, TypeScript still produces JavaScript output. As a result, you can use TypeScript to incrementally type your program, and simply choose to ignore type checking errors. TypeScript only fails to produce output if there's a syntax error, or if you are using TypeScript import statements without specifying a module type.

> but ultimately isn't this isomorphic to the halting problem?

Take a look at http://matt.might.net/articles/intro-static-analysis/

Well, it's kind of uncanny how precisely that article addresses my misconceptions at the outset. Thanks for an awesome link (and the related k-CFA article at the bottom).

Typescript does support incremental conversion, at least according to the talk I saw about it. Most JavaScript files are also valid TypeScript (they say), so starting to use the compiler for your project isn't hard. Also, external libraries can be described with .d.ts files.

It didn't sound like migrating a large codebase would be that hard, assuming you have a consensus about doing it.

Yes, we converted about 16KLoc from JS to TS in ~1 week. The project was working the entire time during the process (the compiler both reported errors and generated JS files)

The TypeScript compiler does indeed barf when it encounters JSX.

TypeScript over Flow

* The language service is superb (and will soon have a documented API). Just try the playground: http://www.typescriptlang.org/Playground/ or Visual Studio. Flow has some sort of open tooling, but its comparatively poor for now (e.g. its autocomplete rarely gives suggestions, needs to be augmented with other tools)

* You can actually export types. Flow lets you do it, but jstransform generates code that throws at runtime (https://github.com/facebook/jstransform/pull/54). This is really annoying and makes Flow unusable for any serious production work right now (for me)

* You can declare modules that are just functions. Flow only lets you declare modules that contain things. This is also annoying and makes Flow unusable with many modules on npm aswell. TypeScript on the other hand has excellent support for all of the following: AMD, CommonJS and object (namespaced) modules. Modules are a bit confusing and rigid and take some time to figure out though.

* Passing all compilation units to the compiler rather than working inside an entire folder based on a config file is a lot more flexible.

* Boudned generics. TypeScript lets you add restrictions to your generics e.g. `interface Set<T extends Eq> { ... }`. Afaik flow doesnt have them yet.

* Faster, more open development. Compare TypeScript's daily commits, code reviews and pull requests with flow's monthly code-dump ("sync changes to upstream")

* Doesn't pretend its not a compile-to-JS language. Flow is being marketed by Facebook as JavaScript but it isn't (maybe they want to avoid being bashed by the coffeescript-hater crowd? having strong type inference does not a JavaScript make) TypeScript clearly states its a compile-to-JS language. Both are pretty much the same thing in this regard.

Flow over TypeScript:

* Much sounder type system. Null and (most) undefined values are properly modeled. Generics don't have weird behavior [1] in some cases. This is truly the best thing Flow has over TS.

* Product types. TypeScript only has function product types (overloads), Flow also supports product types on objects, which is really useful given the nature of JS objects (e.g. lets you model lodash.extend properly)

* A couple of extra ES6 goodies (e.g. destructuring). TypeScript will be catching up soon though.

* Much better type inference. In typescript types stop flowing through functions that are not arguments to function calls. In flow they continue to... erm, flow, so its possible to write most of your module without using any type annotations whatsoever. Now, this might sound like its important, but in practice its not that important - its best to annotate all functions with types anyway as error messages soon become confusing or misleading otherwise (the line where an inconsistency occurred is much further away than the place with the actual error)

* JSX. I find this not-so-useful to be honest, especially with the newest strongly-tied-to-React incarnation of the JSX compiler which is a lot less nicer than the older compiles-to-function-calls version. Though its really nice to have typechecked HTML-like templates, I suppose.

Even more info here:

[1]: https://github.com/Microsoft/TypeScript/issues/1265

I found one other way to use types across modules.

    /* @flow */  
    var Person;  
    type Person = {name: {first: string; last: string;}; isActive: boolean;}  
    module.exports.Person = Person
Just by writing that var you can use the type across modules.

How well does flow play with third party libraries? ie. TypeScript has type definitions that are pretty well established for most commonly used 3rd party libs. I'm wondering if there is a similar project for Flow?

The maybe types `?string` really annoy me.

I will rather wait until TypeScript pleases me with union types and proper es6 alignment.

Really? Why are they annoying?

Optional parameters have ? as postfix too. Resulting code like: function foo(x?:?string):?string { return x; }

I would much rather like a null type, or even better: have null be declared as void too.

This looks similar to the type checking in Google's Closure compiler.


Why has this been downvoted? is the type checking in Google Closure not a good option?

I've had much success with it on a rather large project. shrug

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact