Skip to content

Technical advantages over TypeScript that justify fragmentation? #67

Closed

Description

@SidShaytay

To the engineering team: What are the technical advantages of Flow over Typescript that would justifying fragmenting the 'typed javascript' scene?. Typescript is already open sourced at https://github.com/Microsoft/TypeScript.

I'm hoping this isn't a result of a "not built here syndrome" or other petty politics because at first glance they seem so similar that one might as well join forces and make all developers' lives earlier (tools, workings etc).

PS: Do let me know if there is a more appropriate forum to have this discussion.

Activity

  1. briandipalma commented on Nov 19, 2014

    @briandipalma

    This has been addressed in the videos and documentation on flowtype. One of the reasons is that flow includes type inferences which TS does not have. This means you can type check code without annotations.

  2. avikchaudhuri commented on Nov 19, 2014

    @avikchaudhuri
    Contributor

    Yes, that's the main difference. See also the Overview section of this blog post (a few paras down): https://code.facebook.com/posts/1505962329687926/flow-a-new-static-type-checker-for-javascript/

    [Closing the issue]

  3. Arnavion commented on Nov 23, 2014

    @Arnavion

    One of the reasons is that flow includes type inferences which TS does not have.

    Just for the record, TS does have type inference. What it does differently from Flow (regarding the example in @avikchaudhuri 's link) is that it only infers the return type of the function, not the type of its parameters. It infers unannotated parameters as any.

    It's just a different point on the scale of assuming the validity of unannotated code (aka programmer knows best). The blog post is correct in saying that the incorrect code compiles because TS is more conservative than Flow, but the blanket statement above that TS does not perform any inference without annotations is incorrect.

    For example, this code in TS will complain that the second assignment to x is invalid because foo() has been inferred to return a number, and the declaration of x has caused it to be inferred as a string.

    function foo(x) { return x + 5; } // foo is inferred as (x: any) => number
    var x = "5"; // x is inferred as string
    x = foo(); // Error - Type 'number' is not assignable to 'string'
  4. briandipalma commented on Nov 24, 2014

    @briandipalma

    @Arnavion I didn't realize that, the TS team could do with some better marketing. It's always seemed like you needed to use annotations to gain any value from TS which put me off given that there was still a lot of value from just analyzing standard JS and it was difficult to add a build step to the legacy code I was working on.

  5. avikchaudhuri commented on Nov 24, 2014

    @avikchaudhuri
    Contributor

    @briandipalma No doubt TypeScript does some minimal type inference. However, it is not very principled. For example, pinning down x to string in @Arnavion's example is symptomatic of a larger problem of not playing well with subtyping:

    class A { x: string; }
    class B extends A { y: number; }
    class C extends A { z: number; }

    function foo() {
    var a = new B();
    if (true) a = new C(); // TypeScript reports an error, because a's type is already too narrow
    a.x; // Flow reports no error, because a's type is correctly inferred to be B | C
    }

    On the other hand, TypeScript can quickly infer something to be any. For example, try var x = null.

    Overall, I suspect there is nothing much to say about TypeScript's type inference, beyond it being a set of best-attempt heuristics to get good tooling. (And maybe it is quite sufficient for that purpose.)

  6. Arnavion commented on Nov 24, 2014

    @Arnavion

    @briandipalma TS marketing always says that you take your existing JS and "gradually add type information." For example, the carousel on typescriptlang.org says "These types are optional, and type inference allows a few type annotations to make a big difference to the static verification of your code."

    @avikchaudhuri Definitely. TS doesn't propagate type information "backwards" except in very few circumstances (it does infer the generic types of a function call from its arguments). Flow's typechecker may be better in that respect.

    Automatically inferring any can be prevented by using the --noImplicitAny commandline option (it causes a warning to be printed wherever the compiler infers something to be any without being explicitly annotated as any), but of course it does require an appropriate annotation to be fixed and it's not on by default.

    Personally, Flow has the one feature I sorely miss from TS, which is non-nullable types (as a bonus, they're non-nullable by default). Once Flow catches up to TS in terms of features, I'll switch to Flow in a heartbeat.

  7. YipYipX4 commented on May 10, 2015

    @YipYipX4

    Just my opinion, but I'm not seeing a good justification for fragmentation here. TypeScript could be improved to have better type inference and I'm sure that quality contributions would be accepted. For the cases where TypeScript is more strict (e.g. not allowing types to be changed on-the-fly), I bet that a command-line option could be added to TypeScript to bypass the strictness. Likewise, other options to make TypeScript work as a static JavaScript checker could be added if necessary (i.e. input some *.js files and just output warnings with no output file).

    Also, I happen to agree with not allowing types to change. Is there a lot of JavaScript out there that does this? Wouldn't it be more likely to be a mistake?

    Definitely seems to be a case of Not-Invented-Here syndrome. Am I wrong?

  8. added a commit that references this issue on Jul 31, 2015
  9. freddi301 commented on Mar 6, 2017

    @freddi301

    I use flow.
    But i would prefer to type some extra strokes and do not loose type information.
    Yes, i am refering to 'unknown type' not only in type-at-pos but in code too.

  10. YipYipX4 commented on Nov 16, 2017

    @YipYipX4

    In retrospect, it seems that TypeScript has addressed most (or all) concerns I see in this thread (--allowJs to type check legacy JavaScript, --strictNullChecks to support non-nullable types, improvements in type inferences, etc.).

    If you want to change a type on-the-fly (which smells like something that should normally be an error), I think it is reasonable to have to declare the type as "B | C" or just declare the type as "A" (where B and C are directly derived from A and you only use properties from A).

    Modifying 2 lines from the previously posted example:

    var a: A = new B();  // or   var a: B | C = new B();  
    a = new C(); // TypeScript no longer reports an error
    

    So, are there any technical advantages left that justify not contributing to TypeScript and causing fragmentation?

  11. JoshuaKGoldberg commented on Dec 21, 2017

    @JoshuaKGoldberg

    +1 to the questions thus far. @avikchaudhuri was there ever discussed the option of adding features to TypeScript instead of fragmenting? See YipYipX4's comment - I don't see any advantage of Flow over TypeScript post TS 2.0. It'd be great if there were some documentation page beyond this post that listed the more advanced features...?

  12. apsavin commented on Dec 21, 2017

    @apsavin
    Contributor

    @YipYipX4 @JoshuaKGoldberg TypeScript authors have no aim to make a sound type system. That's the main difference IMO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions