Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Technical advantages over TypeScript that justify fragmentation? #67

Closed
SidShetye opened this issue Nov 19, 2014 · 11 comments
Closed

Technical advantages over TypeScript that justify fragmentation? #67

SidShetye opened this issue Nov 19, 2014 · 11 comments

Comments

@SidShetye
Copy link

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.

@briandipalma
Copy link

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.

@avikchaudhuri
Copy link
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]

@Arnavion
Copy link

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'

@briandipalma
Copy link

@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.

@avikchaudhuri
Copy link
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.)

@Arnavion
Copy link

@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.

@YipYipX4
Copy link

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?

jeffmo pushed a commit to jeffmo/flow that referenced this issue Jul 31, 2015
@freddi301
Copy link

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.

@YipYipX4
Copy link

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?

@JoshuaKGoldberg
Copy link

+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...?

@apsavin
Copy link
Contributor

apsavin commented Dec 21, 2017

@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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants