Skip to content

RFC: Strip and Transform Flow Types to ship Standard JavaScript on React Native Published Package#949

Open
bacarybruno wants to merge 6 commits intoreact-native-community:mainfrom
bacarybruno:strip-flow-types
Open

RFC: Strip and Transform Flow Types to ship Standard JavaScript on React Native Published Package#949
bacarybruno wants to merge 6 commits intoreact-native-community:mainfrom
bacarybruno:strip-flow-types

Conversation

@bacarybruno
Copy link

@bacarybruno bacarybruno commented Oct 19, 2025

Proposal: Ship Standard JavaScript code by stripping/removing Flow syntax from the JavaScript code published to npm in the react-native package. The Flow annotations embedded in the JavaScript source code is becoming a barrier to adopting modern JavaScript tooling like esbuild / swc and all other tools that depend on them, even though separate TypeScript definitions already exist.

Related discussion: #810

View the rendered RFC

@bacarybruno bacarybruno marked this pull request as ready for review October 20, 2025 06:41
@bacarybruno
Copy link
Author

bacarybruno commented Jan 24, 2026

Hi folks, quick ping on this RFC.

I have some bandwidth this quarter to move this forward, but before investing more time I would really appreciate an initial review or high-level feedback to make sure I am heading in the right direction.

@grabbou tagging you since this touches tooling. Would love your take when you have a moment 🙏

@kraenhansen
Copy link

kraenhansen commented Feb 12, 2026

I'm left wondering if / how this would impact the adoption of static Hermes, as it's my current understanding that this type information is needed to effectively AOT compile the bundle.

CC @tmikov

@mikeduminy
Copy link

I spoke to @huntie about this at React Universe and it seemed doable, but I'm also not sure what it could mean for static Hermes. The backwards-compatible approach could be to expose an entrypoint free of flow types as a package exports condition which those wishing to use modern tooling could configure rewrites for.

@huntie
Copy link
Collaborator

huntie commented Feb 12, 2026

@mikeduminy Yes!

@bacarybruno In support of this RFC and agree with the motivations ✅ Thanks for adding the specific tools (I think we can add oxc as well).


Prior art: "noflow" attempt with required build changes

Also talking to @cpojer about this last year, I drafted a "noflow"-flavour attempt that I intended to RFC, with a start made in https://github.com/huntie/react-native/tree/rfc-build-noflow.

This approach kept Flow files by default (with Flow stripping in the build), and a package exports condition to opt out. But now we're thinking we do this by default, with a positive "flow" exports condition (inverse idea).

How we move forward

Let's align and merge this RFC — have left some initial comments.

  • react-native will move to distributing plain JS (ES6+) by default, with types stripped at build time.
  • We'll introduce a new "flow" exports condition, intended for Meta's codebase and Flow users. This will point to the Flow source files.

Unresolved questions:

  • Will the built files overwrite the source codebase locations on publish?
    • Ideally not. This could involve copying more files into a dist/ directory, including dist/src/... — or, some file suffix we map to via the "exports" field.

@bacarybruno Happy to revise the RFC based on this? Ideal if the implementation can be externally driven by someone too — but I'm happy to support the eventual import + review 🙏🏻

date: 2025-10-20
---

# RFC0000: Strip Flow Types from React Native Published Package
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. And we have the RFC # now :)

Suggested change
# RFC0000: Strip Flow Types from React Native Published Package
# RFC0949: Strip Flow Types from Published `react-native` Package


## Summary

This proposal seeks to remove Flow type annotations from the JavaScript code published to npm in the `react-native` package. Currently, React Native ships JavaScript files that contain Flow annotations plus separate TypeScript definition files (`.d.ts`). This proposal would strip the Flow annotations from the JavaScript source files while maintaining the existing TypeScript definitions and adding Flow definition files (`.js.flow`) for Flow users.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Per my incoming comment on the overall approach, let's remove "and adding Flow definition files (.js.flow) for Flow users.". Won't be needed (I think) 🙏🏻

Suggested change
This proposal seeks to remove Flow type annotations from the JavaScript code published to npm in the `react-native` package. Currently, React Native ships JavaScript files that contain Flow annotations plus separate TypeScript definition files (`.d.ts`). This proposal would strip the Flow annotations from the JavaScript source files while maintaining the existing TypeScript definitions and adding Flow definition files (`.js.flow`) for Flow users.
This proposal seeks to modernize the `react-native` npm package by distributing plain JavaScript source code with Flow types stripped. This will help the ecosystem by significantly expanding compatibility with modern JS parsers and tooling, and reducing coupling with the user-land `@react-native/babel-preset`.

@huntie huntie self-assigned this Feb 12, 2026
@cpojer
Copy link
Member

cpojer commented Feb 12, 2026

react-native will move to distributing plain JS (ES6+) by default, with types stripped at build time.
We'll introduce a new "flow" exports condition, intended for Meta's codebase and Flow users. This will point to the Flow source files.

@huntie this is great, and the right direction. Thank you for spending time on this 🙇‍♂️

@kraenhansen
Copy link

But now we're thinking we do this by default, with a positive "flow" exports condition (inverse idea).

That would be great! 🙂

@bacarybruno bacarybruno requested a review from huntie February 13, 2026 08:21
@bacarybruno
Copy link
Author

react-native will move to distributing plain JS (ES6+) by default, with types stripped at build time

Great news indeed! 🙌
I just updated the RFC, thanks for your review and detailed comments 🙏

Ideal if the implementation can be externally driven by someone too

@huntie I'll be happy to work on the implementation once the RFC is merged

@huntie
Copy link
Collaborator

huntie commented Feb 16, 2026

@bacarybruno Thanks! Just shared this internally, just in case the team has any problems to flag. Will reach back.

@robhogan
Copy link

robhogan commented Feb 16, 2026

As a matter of (at least) semantics in the RFC - Flow can’t be “stripped” to JS. Like TypeScript, but moreso, it’s an extension of JS that can (at least for the moment) be transformed per-module to valid JS. Enums, component syntax and matchers are examples of language features that require transforms.

I’d reframe as “ship standard JS” rather than “strip Flow”, but which standard is I think an open question.

@robhogan
Copy link

robhogan commented Feb 16, 2026

The most important question here though IMO is whether removing information from the shipped runtime code turns into compromising performance for the sake of compatibility with additional dev-time tools, which I think most of us would agree is a poor trade off.

And that’s not just in reference to the potential of Static Hermes for native targets, but also transforms like React Compiler, which may be able to use Flow/TS syntax as hints for runtime optimisation.

I appreciate the spirit of suggestions like shipping Flow/TS in parallel under a different export condition to keep all options open, but then we’re shipping two runtimes, where one gives you more tooling flexibility and the other gives you better runtime performance, and neither are guaranteed to have the same behaviour. Is that where we want to be?

@bacarybruno
Copy link
Author

Thanks @robhogan for your feedback.

I'll reframe as “ship standard JS” 👍

I’ll update the wording. To make sure we are aligned, the idea is to apply the same transforms from @react-native/babel-preset so we publish plain JavaScript by default, with the Flow sources available via a separate "flow" export condition.

whether removing information from the shipped runtime code turns into compromising performance for the sake of compatibility with additional dev-time tools

Currently Flow/types aren't part of the shipped runtime as they’re being stripped during bundling by @react-native/babel-preset , so the goal is to primarily move that work to publish-time. It's also clear that we should be careful not to block initiatives like Static Hermes that may want typed sources as input, that was the intent of the "flow" condition.

I may be biased here, but having this 2nd "flow" entrypoint feels like the right middle ground: we can unblock modern tooling by default + still keeping typed sources available for Flow users and related tools. Then it’s on us to ensure the default shipped JS applies the right transforms (same behavior as @react-native/babel-preset).

@bacarybruno
Copy link
Author

I’d reframe as “ship standard JS” rather than “strip Flow”

Done here b6617ef 👍

@bacarybruno bacarybruno changed the title RFC: Strip Flow Types from React Native Published Package RFC: Strip and Transform Flow Types to ship Standard JavaScript on React Native Published Package Feb 18, 2026
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

Successfully merging this pull request may close these issues.

6 participants

Comments