Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm curious what criteria you used to pick Flow vs. Typescript.


We picked Flow because we were using React, and Flow was from Facebook, so we assumed the support/integration would be tighter than with TypeScript. It also had some appealing goals like stronger soundness, and a greater emphasis on type inference than TypeScript had at the time

The main reason we switched was the tooling. The language server was slow in the best of times, would crash constantly, would memory-leak all over the place. Some of our devs stopped running it at all because it was so broken all the time. Then I tried out TypeScript and the speed and stability were breathtaking, and we never looked back.


I personally picked Flow because it was (and still is probably?) a much sounder and stricter type system than TypeScript.

However, keeping up with the constant breaking changes (I helped maintained a few complex flow typedefs) led to me getting disenchanted and burnt out with Flow.

Also, at one point a change was introduced where most (or all) internal errors would just cause a type to decay into `any`s, which frustrated me a lot.

I don't hold it against Flow though; its only customer is the internal React team, and it's a 0.x software too.

We've migrated our code to TypeScript later and it was a bit smoother sailing (although the typedefs for a few popular react ecosystem libraries were just... Abysmally wrong, it didn't matter at the end of the day; it was still easier).


Flow is more sound in a lot of ways (e.g. exact object types, by default!) but it also has huge holes (e.g. it has no equivalent to --no-implicit-any, the single most important strict flag in TS). Neither is strictly more sound than the other.


for a lot of people it was some combination of:

- Flow has more adoption (it did, for a while, in the OSS sphere)

- Microsoft is evil (remember, this was before everyone was using VS Code and loving it. (Also, tautologically, TypeScript has been one of the biggest things that changed this public perception for the people I hang around))

- Facebook is awesome (oh, how times have changed...)

- Flow has total type soundness as a goal (from the beginning, and through to today, TypeScript still lists this as an explicit non-goal)

- You literally cannot use React and Flow together (it didn't support JSX for what felt like an eternity and Flow did from the beginning (I think?).

- Flow had exact object types (TypeScript _sorta_ has this today, but most people don't know to turn it on because it isn't in the strict-mode family: exactOptionalPropertyTypes)

- Flow had more features (and was faster)

- DefinitelyTyped didn't exist yet, and it was easier to find types for Flow (but, let's be real, both had nearly nothing compared to today)


Total type soundness is not a goal of Flow.

For example, array bounds are not considered. Flow considers this program to have no errors, but TypeScript (with the correct option enabled) will:

  let m = [1, 2, 3];
  console.log(m[4].toFixed());
Also, DefinitelyTyped itself launched before Flow (2012 vs 2015), so the timeline on that point isn't right.


TypeScript tries to be sound too. It wouldn't really make sense to write a type checker if that wasn't your goal. As the person who wrote the "100% soundness is a non-goal" line in the design goals document, that's there to serve the same role as "Flow sometimes has to make a tradeoff" in the Flow docs in terms of clarifying whether or not 100% soundness is a design goal. For both projects, the answer is "no".

It's unfortunate that people have, over the years, decided that just being upfront about this fact means that TypeScript has a vastly different prioritization of soundness than Flow. We don't; both checkers use soundness as the default assumption when designing behavior.


> Flow tries to be as sound and complete as possible.

> https://flow.org/en/docs/lang/types-and-expressions/

That's what I was talking about re: Flow.

That's a really insightful comment you make about the "turn of the phrase" between how the two marketed themselves. Super interesting stuff.

also, apologies for messing up the timeline on the DT repo. My memory failed me there. Has it been that long?!?


I am still attracted by Flow which seems to have a simpler and stronger type system. However, Flow seems a bit unstable and the lack of support for TypeScript declaration files and widely used TypeScript syntaxes are stopping me from switching to Flow. I opened an issue for bridging the syntax gap between Flow and TypeScript [0]. Flow v0.201.0 renamed `$Partial` to `Partial` making Flow a bit more compatible with TypeScript. I hope it is just the beginning...

[0] https://github.com/facebook/flow/issues/8989


As an "old person" it still weirds me out to see Microsoft get so much praise for their open-source developer tools


TypeScript could be used with React at least since 2015, that's when I first used that combo in production.


it's going to be really hard for me to find now after all these years but there's a video somewhere on YouTube of someone at a conference showing their first attempts at getting TypeScript to work with JSX involving lots of special comments that they would compile out with babel or something (it's been a few years, hopefully I remember that correctly). It was pretty extreme (and cool!).


Flow still has some better sides:

* first class opaque type support

* exact object type

* correct variance, sound liskov oop

* no transpilation support (/*: */ and /*:: */) - so simple, so powerful; jsdoc ts doesn't compare, you can't import type star, when consuming libraries you have to increase maxNodeModuleJsDepth and other shenanigans; in flow you simply have access to all flow type language; why they don't want to do the same with ts is beyond me, it's like half a day of work to do it?

* nominal types for classes, structural for the rest - as it should be

* correct spread matching runtime behaviour

Flow is under active development. They recently completed ~2 years of work on local type inference which is a big deal. But dev team is not interested in external contributions - quite opposite to how ts development is done.

I did switch to ts as well but do miss above.


Great list!

Related to your point on supporting 0-transpilation workflows as a first class citizen, is the fact that Flow was explicitly just type annotations & checking, and aimed to introduce 0 runtime constructs.

This is something Flow did from the beginning and TypeScript eventually established as a non-goal after already implementing several runtime constructs that they can no longer afford to remove for backwards compat [1].

Though interestingly enough, Flow themselves recently announced they're going to start introducing runtime constructs, which is an interesting plot twist [2].

[1] https://github.com/Microsoft/TypeScript/wiki/TypeScript-Desi...

[2] https://medium.com/flow-type/clarity-on-flows-direction-and-...


In another plot twist TypeScript is supporting the Types as Comments TC39 proposal that would provide a true 0-transpilation workflow.

https://devblogs.microsoft.com/typescript/a-proposal-for-typ...


I remember doing a head to head comparison between Flow and Typescript back in 2015 or sometime around then, and flow came out top at the time. Main pull for flow for me was strict null checking and disjoint unions, which typescript lacked at the time.

About a year later typescript got strict null checks and discriminated unions, and from that point on typescript just kept improving, the community type defintiions kept getting better, and flow felt like it was stagnating and had lots of performance issues (esp on windows machines).

Flow actually still has a few notable features that typescript still lacks but are often asked for. For example, flow as `Exact` types that ensures that an object doesn't have excess properties throughout its lifetime - ergonomics are a bit awkward though.


Typescript in strict mode doesn't allow excess properties in an increasing number of situations. Typescript is still more structurally typed than nominally typed so there's no easy way to opt-in a specific type to stronger checks than average. The ergonomics are obviously different between Typescript and Flow. There are existing practical workarounds today to get more "nominally exact" types in Typescript such as using "brands" of various sorts (the most common is adding a private unique symbol to a type), though the ergonomics of using such branded types is also its own sort of awkward.


Those excessive property checks are pretty limited to basically the construction of object literals, and it does it because its normally an error if you have a very explict type but your literal expression doesn't match it. Typescript really does nothing to enforce anything around excess properties except for that narrow case.

Branding doesn't really enforce anything except what the user asserts is the case. Its not the same thing.


This was fairly early days (I want to say early 2016?), so its fuzzy now (and pre VS code going mainstream which has lowered TS friction pretty significantly) but I think a lot of it was a fairly basic pros/cons list with a lot of reading peoples opinions of using each technology. I think my ultimate reason was that Flow was comment-based and so was technically more "rip out"-able if I changed my mind later.

EDIT: oh, also as someone else mentioned it was a React project, so I'm sure that played a part.


Flow allowed gradual typing of the project and Typescript forced you to convert everything at once(at least the first versions of TS)




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

Search: