I had a hard time convincing a couple of places I worked to use TS rather than Flow for greenfield projects, but I’d tried them both out and concluded Flow just felt too unstable - the server would consume all my memory and crash and it just didn’t feel like a good dev experience. I managed to convince them by showing them how you could strip out Typescript types in much the same way as Flow if TS did turn out to be a dead end. I also recall having vigorous debates at React meetups where I was the only person in favour of TS haha.
How times changed - you definitely can’t be blamed for choosing Flow at the time though as TS was the outsider. Also MS weren’t such a trusted brand for developers, people still associated them with proprietary stuff like .net/full fat Visual Studio and I think a few people had burned out in the MS ecosystem before and didn’t want to touch their stuff again!
I put quite some time into evaluating Flow vs Typescript around 2016, and preferred Flow mostly because its type checking was more correct, and its bugs more straightforward. Typescript would happily compile all sorts of incorrect code even with its strictest configs, it was insane.
I eventually found my happy place with Scala.js.
I actually think the bigger driver for TypeScript was Anders' history of working on C# and Delphi before that.
If Flowtype had more resources from Facebook it could still be the dominating language
Even well after TS was clearly the better option (as in 2022) the twitter web team opposed anything being done in Typescript like separate modules that would be a dependency of the web repo.
At least you recognize the better direction now.
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.
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 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)
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.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.
> 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?!?
* 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.
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-...
https://devblogs.microsoft.com/typescript/a-proposal-for-typ...
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.
Branding doesn't really enforce anything except what the user asserts is the case. Its not the same thing.
EDIT: oh, also as someone else mentioned it was a React project, so I'm sure that played a part.
I went with TypeScript early on because the compiler chain felt better integrated than the alternatives. No messing with chains of babel translators and source mappings; just use one tool. Maybe I liked the syntax better, also. Although as I recall, in the beginning, somebody my company interviewed had set up TypeScript using Babel, and it was all very over-my-head and impressive. He turned out to be too good to work for us, but some of his ideas really stuck with me.
[1]This is why I dislike cutesy names for software projects. Just call it FacebookTypeAnnotatedJavaScriptFrobulator3003 (FTAJSF3003) or something.
What caused you to choose Flow over TypeScript?