discussions-and-proposals
discussions-and-proposals copied to clipboard
Proposal: Change the default app template from Flow to TypeScript or Vanilla JS
Introduction
When creating a new react-native application through react-native init the default template will generate a new project using Flow, with an App.js using Flow, and a flowconfig dropped into the directory (but no flow-check linting). While this default allows for native typings to be used, Flow has not achieved widespread usage in OSS and can cause some confusion for new users. E.g. https://github.com/microsoft/react-native-windows/issues/6596 tracks an issue where a new user to react-native was confused as to why opening App.js in VSCode showed errors in a new app.
Details
OSS familiarity with different languages
While it's challenging to scope to the RN ecosystem, a lot of information about the OSS JavaScript community can be taken from the yearly State of JavaScript Surveys. When evaluating JavaScript flavors TypeScript maintains a high level of awareness and satisfaction. We see a sharp drop-off for looking at other JS derived languages such as ClojureScript or Elm, with Flow not making it onto the survey.
This backs more empirical observations that TS has become the de-facto type-safe language used by the JS community. Empirically, much code that is formerly Flow, such as ejected community modules, have also been moving to TS. TS is also increasingly showing in Facebook supported projects like Jest.
Editor and ecosystem support
Flow has first-class support when using Atom with Nuclide-derived plugins. This setup itself can be finicky, with lack of official support for Windows. The Flow plugin for VSCode is in an especially bad state, with partial support and the requirement of disabling built-in language services. The out-of-box VSCode experience goes as far as to show parse errors when using Flow.
Surveys show VSCode dominating the editor landscape in community usage. The particularly bad story with Flow in the most popular editor for JS causes issues with dev experience.

Third party typings
Most react-native applications will use third-party NPM packages. When preferring type-safe options it is essential to have accurate and up-to-date typings. While some 3P typings for Flow are maintained on flow-typed, the options and support here is much lower than those of TypeScript. Many libraries export their own TS typings, often derived from their own sources. For those that do not provide built-in typings, there are generally high quality typings available on DefinitelyTyped.
Community RN typings
One advantage of Flow is that is acts as a source of truth for internal types of react-native, which is written in Flow. Community typings for react-native are well-maintained, but are sometimes out-of-date compared to internal changes or have bugs. There are active efforts to address this however, such as the work being done by @alloy to generate TS typings from Flow sources.
Discussion points
- Is the "pit of success" for a new react-native project something type-safe?
- Will metro defaults have long-term support for TS?
- Are community TS typings high enough quality to encourage?
- Do we have survey data to understand what RN users specifically are using?
- Is is possible to maintain a TS template in the OSS react-native repo, or default in the CLI to the existing TS template?
I'd like to add that even if the decision is against using TypeScript by default, it'd still be better to remove Flow from the default template.
Fwiw, I think it is totally reasonable for the template to not include Flow / default to TypeScript. We definitely aren't dogmatic that it has to use Flow.
I think the positives are clear, the question to me is how we overcome the challenges that have kept this from happening in the past.
Last time we removed Flow from the template, as we made changes to React Native we cause incompatibilities that broke the template. Flow in the template forced us to keep it working as we made changes.
Theoretically if React Native itself was TypeScript we wouldn't have this problem. That's a non-option though right now though as all of FB mobile products are in Flow.
So the main question is how do we keep the template working? If we aren't worried about that problem then sure, we can probably switch it.
@thymikee mentioned the idea of an interactive mode in the CLI to choose the template, which I think could be a good idea. My general sense is that vanilla JS would be the most accessible option, but most serious applications would want to use something typed.
Re keeping the template working, I have a couple of thoughts.
- What complexity in the template do we see as likely to be broken by RN changes? It seems like App.js is pretty thin now, and bits like the NewAppScreen component is internal to RN. This is good for alternate templates, since they don't need to do too much.
- Some empirical data would be great from folks maintaining the TS template to understand if they're seeing breaks, being out of tree.
- If we had concerns about not being able to statically verify correctness of the template, an alternative might be runtime validation. In react-native-windows we have some tests run on each PR which publish our package to a local npm registry, then goes through the new app flow to make sure a change doesn't break it. With some of the discoveries trying to get 0.64.0-rc.0 out, it seems like coverage of that scenario could be broadly useful in OSS RN CI to quickly catch changes which break new app flow.
New React Native applications are TypeScript by default as of https://github.com/facebook/react-native/commit/aaf1990287088a6b38269174e402143c90683881 🙂.
@NickGerleman Is there a standard way to opt in to an up-to-date vanilla JS template after 0.71? Like a non-typescript equivalent of how --template react-native-template-typescript is mentioned in the <=0.70 docs?
Even better if it's in an info box that also includes a note or link explaining why this is discouraged, with some of the React Native-specific reasons why explicit types are encouraged going forward that newcomers usually haven't considered. Feels like a lot of people will come wanting vanilla JS, so this is a good opportunity to gently steer. To avoid forking and keep one strictly typed source of truth, maybe they could use the same source, and the js template could simply be the .ts template run through tsc (maybe with a comment like "// Untyped JS is not recommended, see [link explaining type benefits]"?)
@AlanSl the previous React Native app template isn't VanillaJS either, it included Flow type.
Yeah, Flow was the original, which is relatively unaligned with real-world usage outside of Meta, but already a typed variant of JS.
Using types offers a lot of goodness for both developer experience and safety, especially true in a project where we do occasionally remove or change APIs. Type safety via codegen is also one of the key benefits we want to offer in the new architecture, so we would ideally give folks an out-of-the-box project to take advantage of that.
You can still use vanilla JS in the new template though, and tsc is configured to allow mixing and matching TypeScript and vanilla JS if you want to typecheck some but not all of your code. We haven't flipped the documentation over to 0.71 yet, but here's a link to the description of how that works: https://reactnative.dev/docs/next/typescript#using-javascript-instead-of-typescript