Flow checks selected JavaScript files before they run
Flow adds static checking to JavaScript without requiring an all-at-once rewrite. Put // @flow at the top of a file, annotate the places that need explicit types, and the checker analyzes that file against the rest of the typed project. A background server watches changes and makes later status checks incremental. That model still makes sense for a large JavaScript codebase where conversion must happen one directory at a time.
The current documentation describes Flow as a typed dialect with familiar features such as keyof, conditional types, mapped types, type guards, and indexed access. It also has its own React component syntax and a match construct for pattern matching. Version 0.329.0 added flow-parser and flow-eslint as replacements for the Hermes-named packages. This is more than a frozen compatibility tool, although adopting its syntax ties source code to the Flow compiler path.
A project needs both the checker and a type-stripping compiler
The normal application setup is modest. Install flow-bin as a development dependency, add a flow package script, and run flow init to create .flowconfig. Flow recommends a per-project version rather than a global install, which is sensible because releases can tighten checks. Only marked files are checked by default, so a team can choose its migration boundary instead of converting every JavaScript file on day 1.
Typed source cannot go straight to an ordinary JavaScript runtime. The getting-started guide offers Babel with @babel/preset-flow and flow-parser, or the lighter flow-remove-types command. Most library definitions are not bundled either; the docs direct users to flow-typed and a flow-typed.config.json environment list. The checker itself requires no hosted account or secret, but a working project also needs those compiler and definition choices.
What happened when we ran it
Our sandbox installed 126 packages with Yarn in 20 seconds, and the dependency tree used 37 MB on disk. The checked-out commit was 3b35c53, run in an unprivileged Debian container with 3 CPUs and 8 GB of RAM. Installation succeeded without a reported error. These numbers cover the repository's available Node install, not the flow-bin experience inside an unrelated application.
The checkout itself was much larger than that dependency folder: 18,817 files, about 1,045,799 lines of source, and 67.3 MB checked out. Our runner found no build script or target, so it skipped the build. It also found no test script or target and skipped tests. There is a tests directory and 1 CI workflow file, but neither fact gives Yarn a command that our harness could execute.
That result should not be read as a failed compiler build. The repository README now documents a Rust route under rust_port: install nightly Rust, use cargo +nightly build, then run cargo +nightly test. An optimized binary uses another Cargo command. We did not run those commands because the supplied lab measurement defines the install, build, and test results for this review. The honest conclusion is narrower: the Node workspace installs, while its root scripts do not expose the project's real build or tests.
Building Flow itself requires nightly Rust, not just Yarn
Contributing to the checker has a heavier toolchain than installing it in an app. GitHub CI builds the Rust workspace with nightly Rust. The optional flow.js build also needs Emscripten 3.1.44, Node, Yarn, the wasm32-unknown-emscripten target, and a specifically dated Rust nightly. That distinction belongs in onboarding notes because a successful 20-second package install does not prepare a machine to compile the checker.
The test documentation adds another layer. Rust's flow dev-tools runtests runner executes the fixtures under tests, where cases store expected output beside source files and .flowconfig files. Contributors must build a Flow binary before invoking that suite. The instructions are usable once found, but standard JavaScript conventions point at empty targets. A newcomer following only yarn will stop before reaching the code that matters.
TypeScript interoperability remains the main adoption cost
Flow's syntax now overlaps substantially with TypeScript, and the project documents the comparison directly. Package compatibility is less equal. Most JavaScript packages publish TypeScript declarations, while Flow tells users to obtain most definitions from a separate flow-typed repository. Open discussion #9091 asks for better TypeScript ecosystem interoperability and describes manual conversion of definitions as a burden. That discussion is user evidence, not a maintainer promise that a converter is coming.
Syntax support also deserves a trial against the actual application. Open issue #9346 reports that an export from statement with a JSON import attribute is rejected by Flow's parser. The report concerns version 0.295.0, so it should not be generalized to every newer parser behavior without retesting. Its open status is enough reason to include modern module syntax in an upgrade fixture before rolling version 0.329.0 across a large repository.
Current releases show maintenance, while upgrades can add errors
The last push was August 27, 2026, and release v0.329.0 was published on August 22. GitHub showed 22,279 stars and 523 open issues and pull requests; a separate issue search counted 516 open issues. The release shipped binaries for Linux on x86_64 and arm64, macOS arm64, and Windows x86_64. Those dates and artifacts show active maintenance rather than a project living on old tags.
Release notes also warn that upgrades may surface new errors. Version 0.329.0 tightened unique symbol use and legacy variance syntax, changed some diagnostic locations, and fixed a server race that could leave it hanging. Existing users should pin the checker, read each release note, and run it across their own typed files before updating CI. New projects should compare that ongoing migration cost with TypeScript's wider declaration supply before choosing Flow-specific language features.

