Almost every single Flow version upgrade is like this — every new version brings a slew of errors due to Flow’s continuous movement away from practicality towards “soundness”.
Agreed. It seems to be endemic to Flow's culture. We use it at my company and the signal/noise ratio of helpful to unhelpful errors hovers around 0.5. A handful of simple flags to relax checks in specific, extremely common cases would cut out 80% of that noise, but requests on GitHub have been shot down in the name of "soundness". Things like allowing null to be implicitly cast to a string, or assuming document.body doesn't need an undefined-check every single time you use it. TypeScript feels like it's written by JavaScript developers who want IDE hints. Flow feels like it's written by OCaml developers who loathe the very language they're adding types to, and are trying to make it something it isn't, with reckless abandon towards actual developer productivity.
This very well could be the reason Flow has been steadily losing mindshare in favor of a total TypeScript monopoly. TypeScript is great, but lack of diversity is a shame regardless.
Flow has built in support for the Language Server Protocol. tsserver doesn't even support LSP. I agree ts has better IDE support but that's in part because they don't use LSP. odd they expect others to follow it when they don't.
LSP is kinda irrelevant to the argument that they feel that TS+VSCode is geared towards real-world productivity, vs the feeling that Flow prioritizes academic goals over devexp.
Correct. JavaScript is fundamentally flexible on certain things, and while it's very helpful to have some assistance with taming that wilderness, it will fundamentally never be perfect, and by fighting the language tooth and nail on things that don't matter, one only creates developer pain.
In plain JavaScript, 'foo' + null == 'foonull'. This isn't always what you want, but in the vast majority of cases if you're creating a string, it's:
1) For displaying to the user
2) Generating a CSS class or something to that effect
In both of these cases the above is quite a reasonable behavior, and will never cause a runtime exception, and very rarely even a business-logic error. But if I'm working with the result of a .find() or a maybe-property on an object type, I now have to add null checks (or at best || '' fallbacks) everywhere, muddling up my code and making it harder to follow.
I’m not sure I agree. I’ve found updating Flow in a rather large monorepo a relatively straightforward process. The changes are usually rather small because the team releases every two weeks. They also manage the update internally within their company’s monorepo so they’ll usually find out about these types of unexpected behavior changes before the community does.
That said, we do rely on automated error excludes (similar to eslint-ignore-next-line) for things that cannot be fixed with codemods. Those errors were always there it’s just now you know about them. Better to stem the bleeding by updating the type checker to the latest version.
Eh. That hasn't been my experience. FWIW, having seen the codebase you're referring to, I don't consider a huge ignore list exactly a success story. The bulk of the work is merely deferred as tech debt at this point.
To be fair, many Flow upgrades are easy, yes. But some are absolutely nightmarish. The 0.85 upgrade was especially painful - it involved some very non-trivial codemods, we couldn't get it right in all cases, and it involved some loss of type safety as well :(
I've also found Flow to be painful to work with when dealing with a multi-repo setup which exports types from source code. It becomes unnecessarily hard to make libraries interoperable because a Flow upgrade in one project can cause a cascade of errors deep in another project's transitive dep. One basically has no actionable recourse other than waiting until all her deps are version-aligned on Flow (or never upgrading).
In that regard, the Typescript pattern of using .d.ts files as a boundary between a library's tsc version and the consumers's tsc version is quite nice and something I'd like to explore more w/ Flow.
> I’ve found updating Flow in a rather large monorepo a relatively straightforward process.
I'm not sure you're being entirely honest here, as we both know through feedback that flow updates in the said monorepo are one of the most burdensome processes for its contributors.
As a maintainer/owner of a monorepo experience, it's crucial to maintain empathy and honesty of how processes such as dependency and tooling updates affect (and are perceived by) its users.
Apologies, lxe. I can tell you're frustrated. If the the Flow upgrade process has been burdensome to others, I'd really like to know. I've always thought we've done a good job of updating internally on the platform team and that it hasn't been a concern for end users. We did run into some pain points in changing configuration options around the unnecessary optional-chaining lint rules but that wasn't related to updating the Flow version. I think you may be conflating those.
There's usually codemods you fan run to help with updating, and there are tools that add suppression warnings in places that error, which you can run after the upgrade. There's also a tool that removes unused suppressions.
In sorry but I would fire anyone that puts soundness in scare quotes. Yes, there are tradeoffs and yes, it's possible MS is doing it wrong, but soundness is well defined. In an industry that already has a dangerous apathy about all forms of correct, I consider this flippant tone inexcusable.
You kinda have to have worked with Flow to understand where this comment is coming from. Basically what tends to happen for Flow upgrades is that some upgrades throw a million new errors with incoherent messages. For things that are already verified to be working and in production. So an upgrade essentially becomes an exercise in making the type checker happy for its own sake, at the expense of not implementing features or fixing real bugs.
Typescript does not have soundness as a primary goal for a very good reason: there's a trade-off between soundness and productivity, especially when threading the large gray area between theoretical soundness and the realities of what constructs the compiler implementation is actually able to handle and what the existing ecosystem throws at it.
What the GP is lamenting is that a lot of changes in Flow create more work for developers, but they don't improve the rate at which it catches bugs in practice.
This very well could be the reason Flow has been steadily losing mindshare in favor of a total TypeScript monopoly. TypeScript is great, but lack of diversity is a shame regardless.