Page Not Found
We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
diff --git a/404.html b/404.html new file mode 100644 index 00000000000..1eb102f767b --- /dev/null +++ b/404.html @@ -0,0 +1,26 @@ + + +
+ + +We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
] extra text
+```
+
+A suppressor can be one of the following:
+- `$FlowFixMe`: for type errors that you intend to fix later
+- `$FlowIssue`: for a type error that you suspect is an issue with Flow
+- `$FlowExpectedError`: for a location where you expect Flow to produce a type error (for instance, when performing an invalid type cast).
+- `$FlowIgnore`: for locations where you want Flow to ignore your code
+
+Note that all of the suppressors behave identically; we simply recommend using them as described here for your own ease of reference.
+
+The `` portion of a suppression is optional, but when included specifies which [error code](#toc-making-suppressions-more-granular-with-error-codes) the suppression affects.
+
+Some examples of suppression comments:
+
+```
+// $FlowFixMe
+
+// $FlowIssue[incompatible-type]
+
+/* $FlowIgnore[prop-missing] some other text here */
+
+/* $FlowFixMe[incompatible-cast] this
+ is a multi-line
+ comment */
+
+{ /* $FlowIssue this is how you suppress errors inside JSX */ }
+```
+
+In order to be a valid suppression comment, there are also some conditions that must be true:
+- No text can precede the suppressor, or come between the suppressor and the code. For example: `// some text then $FlowFixMe` is not a valid suppression, nor is `// $FlowIssue some text [incompatible-type]` or ` //$FlowFixMe [prop-missing]` (note the space here!).
+- Suppressions must be on the line immediately before the error they suppress, otherwise they will not apply.
+
+### Making Suppressions More Granular with Error Codes {#toc-making-suppressions-more-granular-with-error-codes}
+
+Suppressible Flow errors will also have an error code associated with them (after version 0.127). This code concisely describes the type of issue the error is reporting, and is different between different kinds of errors.
+
+In order to prevent suppressions from suppressing different kinds of type errors on the same line (by default suppressions without codes suppress every error on the following line), you can add an error code to your suppression. For example: `// $FlowFixMe[incompatible-cast]` would only suppress errors with the `incompatible-cast` code. So:
+
+```js flow-check
+// $FlowFixMe[incompatible-cast]
+3 as string;
+```
+would report no errors, but
+```js flow-check
+// $FlowFixMe[prop-missing]
+3 as string;
+```
+would still report a type incompatibility.
+
+To suppress multiple error codes on the same line, you can stack suppression comments one after another, and they will all apply to the first non-comment line like so:
+
+```js flow-check
+let y: number | {x : number} = 1;
+
+// $FlowFixMe[incompatible-cast]
+// $FlowFixMe[prop-missing]
+y.x as string;
+```
+
+This will suppress both of the two errors on this line.
diff --git a/_src/faq.md b/_src/faq.md
new file mode 100644
index 00000000000..59a52670d43
--- /dev/null
+++ b/_src/faq.md
@@ -0,0 +1,278 @@
+---
+title: FAQ
+description: Have a question about using Flow? Check here first!
+slug: /faq
+---
+
+## I checked that `foo.bar` is not `null`, but Flow still thinks it is. Why does this happen and how can I fix it?
+
+Flow does not keep track of side effects, so any function call may potentially nullify your check.
+This is called [refinement invalidation](../lang/refinements/#toc-refinement-invalidations). Example:
+
+```js flow-check
+type Param = {
+ bar: ?string,
+}
+function myFunc(foo: Param): string {
+ if (foo.bar) {
+ console.log("checked!");
+ return foo.bar; // Flow errors. If you remove the console.log, it works
+ }
+
+ return "default string";
+}
+```
+
+You can get around this by storing your checked values in local variables:
+
+```js flow-check
+type Param = {
+ bar: ?string,
+}
+function myFunc(foo: Param): string {
+ if (foo.bar) {
+ const bar = foo.bar;
+ console.log("checked!");
+ return bar; // Ok!
+ }
+
+ return "default string";
+}
+```
+
+## I checked that my value is of type A, so why does Flow still believe it's A | B?
+
+Refinement invalidation can also occur variables are updated:
+
+```js flow-check
+type T = string | number;
+
+let x: T = 'hi';
+
+function f() {
+ x = 1;
+}
+
+if (typeof x === 'string') {
+ f();
+ x as string;
+}
+```
+
+A work around would be to make the variable `const` and refactor your code to avoid the reassignment:
+
+```js flow-check
+type T = string | number;
+
+const x: T = 'hi';
+
+function f(x: T): number {
+ return 1;
+}
+
+if (typeof x === 'string') {
+ const xUpdated = f(x);
+ xUpdated as number;
+ x as string;
+}
+```
+
+## I'm in a closure and Flow ignores the if check that asserts that `foo.bar` is defined. Why?
+
+In the previous section we showed how refinements are lost after a function call. The exact same thing happens within closures, since
+Flow does not track how your value might change before the closure is called:
+
+```js flow-check
+const people = [{age: 12}, {age: 18}, {age: 24}];
+const oldPerson: {age: ?number} = {age: 70};
+if (oldPerson.age) {
+ people.forEach(person => {
+ console.log(`The person is ${person.age} and the old one is ${oldPerson.age}`);
+ })
+}
+```
+
+The solution here is to move the if check in the `forEach`, or to assign the `age` to an intermediate variable:
+
+```js flow-check
+const people = [{age: 12}, {age: 18}, {age: 24}];
+const oldPerson: {age: ?number} = {age: 70};
+if (oldPerson.age) {
+ const age = oldPerson.age;
+ people.forEach(person => {
+ console.log(`The person is ${person.age} and the old one is ${age}`);
+ })
+}
+```
+
+## But Flow should understand that this function cannot invalidate this refinement, right?
+
+Flow is not [complete](../lang/types-and-expressions/#toc-soundness-and-completeness), so it cannot check all code perfectly. Instead,
+Flow will make conservative assumptions to try to be sound.
+
+## Why can't I use a function in my if-clause to check the type of a property?
+
+Flow doesn't track [refinements](.././lang/refinements/) made in separate function calls:
+
+```js flow-check
+const add = (first: number, second: number) => first + second;
+const val: string | number = 1;
+const isNumber = (x: mixed): boolean => typeof x === 'number';
+if (isNumber(val)) {
+ add(val, 2);
+}
+```
+
+However, you can annotate your function with a [type guard](../types/type-guards/) to get this behavior:
+
+```js flow-check
+const add = (first: number, second: number) => first + second;
+const val: string | number = 1;
+// Return annotation updated:
+const isNumber = (x: mixed): x is number => typeof x === 'number';
+if (isNumber(val)) {
+ add(val, 2);
+}
+```
+
+## Why can't I pass an `Array` to a function that takes an `Array`
+
+The function's argument allows `string` values in its array, but in this case Flow prevents the original array from receiving a `number`.
+Inside the function, you would be able to push a `number` to the argument array, causing the type of the original array to no longer be accurate.
+
+You can fix this error by changing the type of the argument to `$ReadOnlyArray`, making it [covariant](../lang/variance/#toc-covariance).
+This prevents the function body from pushing anything to the array, allowing it to accept narrower types.
+
+As an example, this would not work:
+
+```js flow-check
+const fn = (arr: Array) => {
+ arr.push(123); // Oops! Array was passed in - now inaccurate
+ return arr;
+};
+
+const arr: Array = ['abc'];
+
+fn(arr); // Error!
+```
+
+but with `$ReadOnlyArray` you can achieve what you were looking for:
+
+```js flow-check
+const fn = (arr: $ReadOnlyArray) => {
+ // arr.push(321); NOTE! Since you are using $ReadOnlyArray<...> you cannot push anything to it
+ return arr;
+};
+
+const arr: Array = ['abc'];
+
+fn(arr);
+```
+
+## Why can't I pass `{a: string}` to a function that takes `{a: string | number}`
+
+The function argument allows `string` values in its field, but in this case Flow prevents the original object from having a `number` written to it.
+Within the body of the function you would be able to mutate the object so that the property `a` would receive a `number`, causing the type of the original object to no longer be accurate.
+
+You can fix this error by making the property [covariant](../lang/variance/#toc-covariance) (read-only): `{+a: string | number}`.
+This prevents the function body from writing to the property, making it safe to pass more restricted types to the function.
+
+As an example, this would not work:
+
+```js flow-check
+const fn = (obj: {a: string | number}) => {
+ obj.a = 123; // Oops! {a: string} was passed in - now inaccurate
+ return obj;
+};
+
+const object: {a: string} = {a: 'str' };
+
+fn(object); // Error!
+```
+
+but with a covariant property you can achieve what you were looking for:
+
+```js flow-check
+const fn = (obj: {+a: string | number}) => {
+ // obj.a = 123 NOTE! Since you are using covariant {+a: string | number}, you can't mutate it
+ return obj;
+};
+
+const object: {a: string} = { a: 'str' };
+
+fn(object);
+```
+
+## Why can't I refine a union of objects?
+
+There are two potential reasons:
+1. You are using inexact objects.
+2. You are destructuring the object. When destructuring, Flow loses track of object properties.
+
+Broken example:
+
+```js flow-check
+type Action =
+ | {type: 'A', payload: string}
+ | {type: 'B', payload: number};
+
+// Not OK
+const fn = ({type, payload}: Action) => {
+ switch (type) {
+ case 'A': return payload.length; // Error!
+ case 'B': return payload + 10;
+ }
+}
+```
+
+Fixed example:
+
+```js flow-check
+type Action =
+ | {type: 'A', payload: string}
+ | {type: 'B', payload: number};
+
+// OK
+const fn = (action: Action) => {
+ switch (action.type) {
+ case 'A': return action.payload.length;
+ case 'B': return action.payload + 10;
+ }
+}
+```
+
+## I got a "Missing type annotation" error. Where does it come from?
+
+Flow requires type annotations at module boundaries to make sure it can scale. To read more about that, check out our [blog post](https://medium.com/flow-type/asking-for-required-annotations-64d4f9c1edf8) about that.
+
+The most common case you'll encounter is when exporting a function or React component. Flow requires you to annotate inputs. For instance in this example, Flow will complain:
+
+```js flow-check
+export const add = a => a + 1;
+```
+
+The fix here is to add types to the parameters of `add`:
+
+```js flow-check
+export const add = (a: number): number => a + 1;
+```
+
+To see how you can annotate exported React components, check out our docs on [HOCs](../react/hoc/#toc-exporting-wrapped-components).
+
+There are other cases where this happens, and they might be harder to understand. You'll get an error like `Missing type annotation for U` For instance, you wrote this code:
+
+```js flow-check
+const array = ['a', 'b']
+export const genericArray = array.map(a => a)
+```
+
+Here, Flow will complain on the `export`, asking for a type annotation. Flow wants you to annotate exports returned by a generic function. The type of `Array.prototype.map` is `map(callbackfn: (value: T, index: number, array: Array) => U, thisArg?: any): Array`. The `` corresponds to what is called a [generic](../types/generics/), to express the fact that the type of the function passed to map is linked to the type of the array.
+
+Understanding the logic behind generics might be useful, but what you really need to know to make your typings valid is that you need to help Flow to understand the type of `genericArray`.
+
+You can do that by annotating the exported constant:
+
+```js flow-check
+const array = ['a', 'b']
+export const genericArray: Array = array.map(a => a)
+```
diff --git a/_src/getting-started.md b/_src/getting-started.md
new file mode 100644
index 00000000000..981862a45fc
--- /dev/null
+++ b/_src/getting-started.md
@@ -0,0 +1,23 @@
+---
+title: Getting Started
+slug: /getting-started
+description: Never used a type system before or just new to Flow? Let's get you up and running in a few minutes.
+---
+
+Flow is a static type checker for your JavaScript code. It does a lot of work
+to make you more productive. Making you code faster, smarter, more confidently,
+and to a bigger scale.
+
+Flow checks your code for errors through **static type annotations**. These
+_types_ allow you to tell Flow how you want your code to work, and Flow will
+make sure it does work that way.
+
+```js flow-check
+function square(n: number): number {
+ return n * n;
+}
+
+square("2"); // Error!
+```
+
+First step: [install Flow](../install).
diff --git a/_src/index.md b/_src/index.md
new file mode 100644
index 00000000000..01ae475b7ad
--- /dev/null
+++ b/_src/index.md
@@ -0,0 +1,13 @@
+---
+title: Documentation
+description: Guides and references for all you need to know about Flow
+displayed_sidebar: docsSidebar
+spug: /
+---
+
+Guides and references for all you need to know about Flow.
+
+import DocCardList from '@theme/DocCardList';
+import docsCategories from '../src/js/docs-categories';
+
+
diff --git a/_src/install.md b/_src/install.md
new file mode 100644
index 00000000000..f6c28ebbba4
--- /dev/null
+++ b/_src/install.md
@@ -0,0 +1,165 @@
+---
+title: Installation
+slug: /install
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Setup Compiler
+
+First you'll need to setup a compiler to strip away Flow types. You can
+choose between [Babel](http://babeljs.io/) and
+[flow-remove-types](https://github.com/facebook/flow/tree/master/packages/flow-remove-types).
+
+
+
+
+[Babel](http://babeljs.io/) is a compiler for JavaScript code that has
+support for Flow. Babel will take your Flow code and strip out any type
+annotations. If you already use Babel in your project, see [using Babel](../tools/babel).
+
+First install `@babel/core`, `@babel/cli`, `@babel/preset-flow`, and `babel-plugin-syntax-hermes-parser` with
+either [Yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/).
+
+```bash npm2yarn
+npm install --save-dev @babel/core @babel/cli @babel/preset-flow babel-plugin-syntax-hermes-parser
+```
+
+Next you need to create a `.babelrc` file at the root of your project with the `@babel/preset-flow` preset and `babel-plugin-syntax-hermes-parser` plugin.
+
+```json
+{
+ "presets": ["@babel/preset-flow"],
+ "plugins": ["babel-plugin-syntax-hermes-parser"],
+}
+```
+
+If you then put all your source files in a `src` directory you can compile them
+to another directory by running:
+
+```bash
+./node_modules/.bin/babel src/ -d lib/
+```
+
+You can add this to your `package.json` scripts easily, alongside your `"devDependencies"` on Babel.
+
+```json
+{
+ "name": "my-project",
+ "main": "lib/index.js",
+ "scripts": {
+ "build": "babel src/ -d lib/",
+ "prepublish": "yarn run build"
+ }
+}
+```
+
+> **Note:** You'll probably want to add a `prepublish` script that runs this
+> transform as well, so that it runs before you publish your code to the npm
+> registry.
+
+
+
+
+[flow-remove-types](https://github.com/facebook/flow/tree/master/packages/flow-remove-types) is a small
+CLI tool for stripping Flow type annotations from files. It's a lighter-weight
+alternative to Babel for projects that don't need everything Babel provides.
+
+First install `flow-remove-types` with either
+[Yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/).
+
+```bash npm2yarn
+npm install --save-dev flow-remove-types
+```
+
+If you then put all your source files in a `src` directory you can compile them
+to another directory by running:
+
+```sh
+./node_modules/.bin/flow-remove-types src/ -d lib/
+```
+
+You can add this to your `package.json` scripts easily, alongside your `"devDependencies"` on `flow-remove-types`.
+
+```json
+{
+ "name": "my-project",
+ "main": "lib/index.js",
+ "scripts": {
+ "build": "flow-remove-types src/ -d lib/",
+ "prepublish": "yarn run build"
+ }
+}
+```
+
+> **Note:** You'll probably want to add a `prepublish` script that runs this
+> transform as well, so that it runs before you publish your code to the npm
+> registry.
+
+
+
+
+## Setup Flow
+
+Flow works best when installed per-project with explicit versioning rather than
+globally.
+
+Luckily, if you're already familiar with `npm` or `yarn`, this process should
+be pretty familiar!
+
+### Add a `devDependency` on the `flow-bin` npm package
+
+```bash npm2yarn
+npm install --save-dev flow-bin
+```
+
+### Add a `"flow"` script to your `package.json`
+
+```json
+{
+ "name": "my-flow-project",
+ "version": "1.0.0",
+ "devDependencies": {
+ "flow-bin": "^0.232.0"
+ },
+ "scripts": {
+ "flow": "flow"
+ }
+}
+```
+
+### Run Flow
+
+The first time, run:
+
+```bash npm2yarn
+npm run flow init
+```
+
+```
+> my-flow-project@1.0.0 flow /Users/Projects/my-flow-project
+> flow "init"
+```
+
+After running `flow` with `init` the first time, run:
+
+```bash npm2yarn
+npm run flow
+```
+
+```
+> my-flow-project@1.0.0 flow /Users/Projects/my-flow-project
+> flow
+
+No errors!
+```
+
+## Setup ESLint
+
+If you use ESLint, you can read [our page on ESLint](../tools/eslint) to set it up to support Flow.
diff --git a/_src/lang/annotation-requirement.md b/_src/lang/annotation-requirement.md
new file mode 100644
index 00000000000..4a7804565a6
--- /dev/null
+++ b/_src/lang/annotation-requirement.md
@@ -0,0 +1,311 @@
+---
+title: Annotation Requirement
+slug: /lang/annotation-requirement
+---
+
+> **Note:** As of version 0.199 Flow uses [Local Type Inference](https://medium.com/flow-type/local-type-inference-for-flow-aaa65d071347) as its inference algorithm.
+The rules in this section reflect the main design features in this inference scheme.
+
+Flow tries to avoid requiring type annotation for parts of programs where types can easily
+be inferred from the immediate context of an expression, variable, parameter, etc.
+
+## Variable declarations
+
+Take for example the following variable definition
+```js
+const len = "abc".length;
+```
+All information necessary to infer the type of `len` is included in the initializer
+`"abc".length`. Flow will first determine that `"abc"` is a string, and then that the
+`length` property of a string is a number.
+
+The same logic can be applied for all `const`-like initializations. Where things
+get a little more complicated is when variable initialization spans across multiple statements,
+for example in
+```js flow-check
+declare const maybeString: ?string;
+
+let len;
+if (typeof maybeString === "string") {
+ len = maybeString.length;
+} else {
+ len = 0;
+}
+```
+Flow can still determine that `len` is a `number`, but in order to do so it looks
+ahead to multiple initializer statements. See section on [variable declarations](../variables)
+for details on how various initializer patterns determine the type of a variable,
+and when an annotation on a variable declaration is necessary.
+
+## Function Parameters
+
+Unlike variable declarations, this kind of "lookahead" reasoning cannot be used to determine
+the type of function parameters. Consider the function
+```js
+function getLength(x) {
+ return x.length;
+}
+```
+There are many kinds of `x` on which we could access and return a `length` property:
+an object with a `length` property, or a string, just to name a few. If later on in
+the program we had the following calls to `getLength`
+```js
+getLength("abc");
+getLength({length: 1});
+```
+one possible inference would be that `x` is a `string | { length: number }`. What this implies,
+however, is that the type of `getLength` is determined by any part of the current
+program. This kind of global reasoning can lead to surprising action-at-a-distance
+behavior, and so is avoided. Instead, Flow requires that function parameters are annotated. Failure to
+provide such a type annotation manifests as a `[missing-local-annot]` error on the parameter `x`,
+and the body of the function is checked with `x: any`:
+```js flow-check
+function getLength(x) {
+ return x.length;
+}
+
+const n = getLength(1); // no error since getLength's parameter type is 'any'
+```
+
+To fix this error, one can simply annotate `x` as
+```js flow-check
+function getLength(x: string) {
+ return x.length;
+}
+```
+The same requirement holds for class methods
+```js flow-check
+class WrappedString {
+ data: string;
+ setStringNoAnnotation(x) {
+ this.data = x;
+ }
+ setString(x: string) {
+ this.data = x;
+ }
+}
+```
+
+## Contextual Typing {#toc-contextual-typing}
+
+Function parameters do not always need to be explicitly annotated. In the case of a
+callback function to a function call, the parameter type can easily
+be inferred from the immediate context. Consider for example the following code
+```js
+const arr = [0, 1, 2];
+const arrPlusOne = arr.find(x => x % 2 === 1);
+```
+Flow infers that the type of `arr` is `Array`. Combining this with the builtin
+information for `Array.find`, Flow can determine that the type of `x => x % 2 + 1`
+needs to be `number => mixed`. This type acts as a *hint* for Flow and provides enough
+information to determine the type of `x` as `number`.
+
+Any attendant annotation can potentially act as a hint to a function parameter, for example
+```js flow-check
+const fn1: (x: number) => number = x => x + 1;
+```
+However, it is also possible that an annotation cannot be used as a function
+parameter hint:
+```js flow-check
+const fn2: mixed = x => x + 1;
+```
+In this example the `mixed` type simply does not include enough information to
+extract a candidate type for `x`.
+
+Flow can infer the types for unannotated parameters even when they are nested within
+other expressions like objects. For example in
+in
+```js flow-check
+const fn3: {f: (number) => void} = {f: (x) => {x as string}};
+```
+Flow will infer `number` as the type of `x`, and so the cast fails.
+
+
+## Function Return Types {#toc-function-return-types}
+
+Unlike function parameters, a function's return type does not need to be annotated in general.
+So the above definition of `getLength` won't raise any Flow errors.
+
+There are, however, a couple of notable exceptions to this rule. The first one is
+class methods. If we included to the `WrappedString` class a `getString` method
+that returns the internal `data` property:
+```js flow-check
+class WrappedString {
+ data: string;
+ getString(x: string) {
+ return this.data;
+ }
+}
+```
+Flow would complain that `getString` is missing an annotation on the return.
+
+The second exception is recursive definitions. A trivial example of this would be
+```js flow-check
+function foo() {
+ return bar();
+}
+
+function bar() {
+ return foo();
+}
+```
+The above code raises a `[definition-cycle]` error, which points to the two locations
+that form a dependency cycle, the two missing return annotations. Adding
+a return annotation to either function would resolve the issue.
+
+Effectively, the requirement on an annotation for method returns is a special-case
+of the recursive definition restriction. The recursion is possible through access on
+`this`.
+
+## Generic Calls {#toc-generic-calls}
+
+In calls to [generic functions](../../types/generics) the type of the result may
+depend on the types of the values passed in as arguments.
+This section discusses how this result is computed, when type arguments are not
+explicitly provided.
+
+Consider for example the definition
+```js
+declare function map(
+ f: (T) => U,
+ array: $ReadOnlyArray,
+): Array;
+```
+and a potential call with arguments `x => x + 1` and `[1, 2, 3]`:
+```js
+map(x => x + 1, [1, 2, 3]);
+```
+Here Flow infers that the type of `x` is `number`.
+
+Some other common examples of generic calls are calling the constructor of the generic
+[`Set` class](https://github.com/facebook/flow/blob/82f88520f2bfe0fa13748b5ead711432941f4cb9/lib/core.js#L1799-L1801)
+or calling `useState` from the React library:
+```js flow-check
+const set = new Set([1, 2, 3]);
+
+import {useState} from 'react';
+const [num, setNum] = useState(42);
+```
+Flow here infers that the type of `set` is `Set`, and that `num` and `setNum`
+are `number` and `(number) => void`, respectively.
+
+### Computing a Solution
+
+Computing the result of a generic call amounts to:
+1. coming up with a solution for `T` and `U` that does not contain generic parts,
+2. replacing `T` and `U` with the solution in the signature of `map`, and
+3. performing a call to this new signature of `map`.
+
+This process is designed with two goals in mind:
+* *Soundness*. The results need to lead to a correct call when we reach step (3).
+* *Completeness*. The types Flow produces need to be as precise and informative as possible,
+to ensure that other parts of the program will be successfully checked.
+
+Let's see how these two goals come into play in the `map` example from above.
+
+Flow detects that `$ReadOnlyArray` needs to be compatible with the type of `[1, 2, 3]`.
+It can therefore infer that `T` is `number`.
+
+With the knowledge of `T` it can now successfully check `x => x + 1`. The parameter `x`
+is contextually typed as `number`, and thus the result `x + 1` is also a number.
+This final constraint allows us to compute `U` as a `number` too.
+
+The new signature of `map` after replacing the generic parts with the above solution
+is
+```js
+(f: (number) => number, array: $ReadOnlyArray) => Array
+```
+It is easy to see that the call would be successfully checked.
+
+### Errors during Polymorphic Calls
+
+If the above process goes on smoothly, you should not be seeing any errors associated with the call.
+What happens though when this process fails?
+
+There are two reasons why this process could fail:
+
+#### Under-constrained Type Parameters
+
+There are cases where Flow might not have enough information to decide the type of a type parameter.
+Let's examine again a call to the builtin generic
+[`Set` class](https://github.com/facebook/flow/blob/82f88520f2bfe0fa13748b5ead711432941f4cb9/lib/core.js#L1799-L1801)
+constructor, this time without passing any arguments:
+```js flow-check
+const set = new Set();
+set.add("abc");
+```
+During the call to `new Set`, we are not providing enough information for Flow to
+determine the type for `T`, even though the subsequent call to `set.add` clearly
+implies that `T` will be a string. Remember that inference of type arguments is
+local to the call, so Flow will not attempt to look ahead in later statements
+to determine this.
+
+In the absence of information, Flow would be at liberty to infer *any* type
+as `T`: `any`, `mixed`, `empty`, etc.
+This kind of decision is undesirable, as it can lead to surprising results.
+For example, if we silently decided on `Set` then the call to `set.add("abc")` would
+fail with an incompatibility between `string` and `empty`, without a clear indication
+of where the `empty` came from.
+
+So instead, in situations like this, you'll get an `[underconstrained-implicit-instantiation]` error.
+The way to fix this error is by adding a type annotation. There a few potential ways to do this:
+
+- Add an annotation at the call-site in one of two ways:
+ * an explicit type argument
+ ```js
+ const set = new Set();
+ ```
+ * an annotation on the initialization variable:
+ ```js
+ const set: Set = new Set();
+ ```
+
+- Add a default type on the type parameter `T` at the definition of the class:
+ ```js
+ declare class SetWithDefault extends $ReadOnlySet {
+ constructor(iterable?: ?Iterable): void;
+ // more methods ...
+ }
+ ```
+ In the absence of any type information at the call-site, Flow will use the default
+ type of `T` as the inferred type argument:
+ ```js
+ const defaultSet = new SetWithDefault(); // defaultSet is SetWithDefault
+ ```
+
+#### Incompatibility Errors
+
+Even when Flow manages to infer non-generic types for the type parameters in a generic
+call, these types might still lead to incompatibilities either in the current call or in
+code later on.
+
+For example, if we had the following call to `map`:
+```js flow-check
+declare function map(f: (T) => U, array: $ReadOnlyArray): Array;
+map(x => x + 1, [{}]);
+```
+Flow will infer `T` as `{}`, and therefore type `x` as `{}`. This will cause an error when checking the arrow function
+since the `+` operation is not allowed on objects.
+
+Finally, a common source of errors is the case where the inferred type in a generic
+call is correct for the call itself, but not indicative of the expected use later in the code.
+For example, consider
+```js flow-check
+import {useState} from 'react';
+const [str, setStr] = useState("");
+
+declare const maybeString: ?string;
+setStr(maybeString);
+```
+Passing the string `""` to the call to `useState` makes Flow infer `string` as the type
+of the state. So `setStr` will also expect a `string` as input when called later on,
+and therefore passing a `?string` will be an error.
+
+Again, to fix this error it suffices to annotate the expected "wider" type of state
+when calling `useState`:
+```js
+const [str, setStr] = useState("");
+```
+
+## Empty Array Literals {#toc-empty-array-literals}
+Empty array literals (`[]`) are handled specially in Flow. You can read about their [behavior and requirements](../../types/arrays/#toc-empty-array-literals).
diff --git a/_src/lang/depth-subtyping.md b/_src/lang/depth-subtyping.md
new file mode 100644
index 00000000000..d77206e51a3
--- /dev/null
+++ b/_src/lang/depth-subtyping.md
@@ -0,0 +1,68 @@
+---
+title: Depth Subtyping
+slug: /lang/depth-subtyping
+---
+
+Assume we have two [classes](../../types/classes), which have a subtype relationship using `extends`:
+
+```js flow-check
+class Person {
+ name: string;
+}
+class Employee extends Person {
+ department: string;
+}
+```
+
+It's valid to use an `Employee` instance where a `Person` instance is expected.
+
+```js flow-check
+class Person { name: string }
+class Employee extends Person { department: string }
+
+const employee: Employee = new Employee();
+const person: Person = employee; // OK
+```
+
+However, it is not valid to use an object containing an `Employee` instance
+where an object containing a `Person` instance is expected.
+
+```js flow-check
+class Person { name: string }
+class Employee extends Person { department: string }
+
+const employee: {who: Employee} = {who: new Employee()};
+const person: {who: Person} = employee; // Error
+```
+
+This is an error because objects are mutable. The value referenced by the
+`employee` variable is the same as the value referenced by the `person`
+variable.
+
+```js
+person.who = new Person();
+```
+
+If we write into the `who` property of the `person` object, we've also changed
+the value of `employee.who`, which is explicitly annotated to be an `Employee`
+instance.
+
+If we prevented any code from ever writing a new value to the object through
+the `person` variable, it would be safe to use the `employee` variable. Flow
+provides a syntax for this:
+
+```js flow-check
+class Person { name: string }
+class Employee extends Person { department: string }
+
+const employee: {who: Employee} = {who: new Employee()};
+const person: {+who: Person} = employee; // OK
+person.who = new Person(); // Error!
+```
+
+The plus sign `+` indicates that the `who` property is [covariant](../variance/#toc-covariance).
+Using a covariant property allows us to use objects which have subtype-compatible
+values for that property. By default, object properties are invariant, which allow
+both reads and writes, but are more restrictive in the values they accept.
+
+Read more about [property variance](../variance/).
diff --git a/_src/lang/lazy-modes.md b/_src/lang/lazy-modes.md
new file mode 100644
index 00000000000..2d10c3807dc
--- /dev/null
+++ b/_src/lang/lazy-modes.md
@@ -0,0 +1,67 @@
+---
+title: Lazy Mode
+slug: /lang/lazy-modes
+---
+
+By default, the Flow server will typecheck all your code. This way it can answer
+questions like "are there any Flow errors anywhere in my code". This is very
+useful for tooling, like a continuous integration hook which prevents code
+changes which introduce Flow errors.
+
+However, sometimes a Flow user might not care about all the code. If they are
+editing a file `foo.js`, they might only want Flow to typecheck the subset of
+the repository needed to answer questions about `foo.js`. Since Flow would only
+check a smaller number of files, this would be faster. This is the motivation
+behind Flow's lazy mode.
+
+## Classifying Files {#toc-classifying-files}
+
+Lazy mode classifes your code into four categories:
+
+1. **Focused files**. These are the files which the user cares about.
+2. **Dependent files**. These are the files which depend on the focused files.
+Changes to the focused files might cause type errors in the dependent files.
+3. **Dependency files**. These are the files which are needed in order to
+typecheck the focused or dependent files.
+4. **Unchecked files**. All other files.
+
+Lazy mode will still find all the JavaScript files and parse them. But it won't
+typecheck the unchecked files.
+
+## Choosing Focused Files {#toc-choosing-focused-files}
+
+Flow will focus files when they change on disk, using Flow's built-in file watcher
+("dfind") or Watchman.
+
+So, all files that change while Flow is running will be focused. But what about
+files that change when Flow is not running? If you're using Git or Mercurial,
+Flow will ask it for all of the files that have changed since the mergebase
+with "master" (the common ancestor of the current commit and the master branch).
+
+If you're not using "master" (e.g. "main" instead), you can change this with
+the `file_watcher.mergebase_with` config. If you're working from a clone, you
+might want to set this to "origin/master" (for Git), which will focus all files
+that have changed locally, even if you commit to your local "master" branch.
+
+The net result is that Flow will find the same errors in lazy mode as in a full
+check, so long as there are no errors upstream. For example, if your CI ensures
+that there are no errors in "master," then it's redundant for Flow to check all
+of the unchanged files for errors that can't exist.
+
+## Using Lazy Mode {#toc-using-lazy-mode}
+
+To enable lazy mode, set `lazy_mode=true` in the `.flowconfig`.
+
+To start Flow in lazy mode manually, run
+
+```bash
+flow start --lazy-mode true
+```
+
+## Forcing Flow to Treat a File as Focused {#toc-forcing-flow-to-treat-a-file-as-focused}
+
+You can force Flow to treat one or more files as focused from the CLI.
+
+```bash
+flow force-recheck --focus path/to/A.js path/to/B.js
+```
diff --git a/_src/lang/nominal-structural.md b/_src/lang/nominal-structural.md
new file mode 100644
index 00000000000..d28d4bd1fea
--- /dev/null
+++ b/_src/lang/nominal-structural.md
@@ -0,0 +1,141 @@
+---
+title: Nominal & Structural Typing
+slug: /lang/nominal-structural
+---
+
+A static type checker can use either the name (nominal typing) or the structure (structural typing)
+of types when comparing them against other types (like when checking if one is a [subtype](../subtypes) of another).
+
+## Nominal typing {#toc-nominal-typing}
+
+Languages like C++, Java, and Swift have primarily nominal type systems.
+
+```js
+// Pseudo code: nominal system
+class Foo { method(input: string) { /* ... */ } }
+class Bar { method(input: string) { /* ... */ } }
+
+let foo: Foo = new Bar(); // Error!
+```
+
+In this pseudo-code example, the nominal type system errors even though both classes have a method of the same name and type.
+This is because the name (and declaration location) of the classes is different.
+
+## Structural typing {#toc-structural-typing}
+
+Languages like Go and Elm have primarily structural type systems.
+
+```js
+// Pseudo code: structural system
+class Foo { method(input: string) { /* ... */ } }
+class Bar { method(input: string) { /* ... */ } }
+
+let foo: Foo = new Bar(); // Works!
+```
+
+In this pseudo-code example, the structural type system allows a `Bar` to be used as a `Foo`,
+since both classes have methods and fields of the same name and type.
+
+If the shape of the classes differ however, then a structural system would produce an error:
+
+```js
+// Pseudo code
+class Foo { method(input: string) { /* ... */ } }
+class Bar { method(input: number) { /* ... */ } }
+
+let foo: Foo = new Bar(); // Error!
+```
+
+We've demonstrated both nominal and structural typing of classes, but there are
+also other complex types like objects and functions which can also be either
+nominally or structurally compared.
+Additionally, a type system may have aspects of both structural and nominal systems.
+
+## In Flow
+
+Flow uses structural typing for objects and functions, but nominal typing for classes.
+
+### Functions are structurally typed {#toc-functions-are-structurally-typed}
+
+When comparing a [function type](../../types/functions) with a function it must have the same structure
+in order to be considered valid.
+
+```js flow-check
+type FuncType = (input: string) => void;
+function func(input: string) { /* ... */ }
+let test: FuncType = func; // Works!
+```
+
+### Objects are structurally typed {#toc-objects-are-structurally-typed}
+
+When comparing an [object type](../../types/objects) with an object it must have the same structure
+in order to be considered valid.
+
+```js flow-check
+type ObjType = {property: string};
+let obj = {property: "value"};
+let test: ObjType = obj; // Works
+```
+
+### Classes are nominally typed {#toc-classes-are-nominally-typed}
+
+When you have two [classes](../../types/classes) with the same structure, they still are not
+considered equivalent because Flow uses nominal typing for classes.
+
+```js flow-check
+class Foo { method(input: string) { /* ... */ } }
+class Bar { method(input: string) { /* ... */ } }
+let test: Foo = new Bar(); // Error!
+```
+
+If you wanted to use a class structurally you could do that using an [interface](../../types/interfaces):
+
+```js flow-check
+interface Interface {
+ method(value: string): void;
+};
+
+class Foo { method(input: string) { /* ... */ } }
+class Bar { method(input: string) { /* ... */ } }
+
+let test1: Interface = new Foo(); // Works
+let test2: Interface = new Bar(); // Works
+```
+
+### Opaque types
+You can use [opaque types](../../types/opaque-types) to turn a previously structurally typed alias into a nominal one (outside of the file that it is defined).
+
+```js flow-check
+// A.js
+export type MyTypeAlias = string;
+export opaque type MyOpaqueType = string;
+
+const x: MyTypeAlias = "hi"; // Works
+const y: MyOpaqueType = "hi"; // Works
+```
+
+In a different file:
+
+```js
+// B.js
+import type {MyTypeAlias, MyOpaqueType} from "A.js";
+
+const x: MyTypeAlias = "hi"; // Works
+const y: MyOpaqueType = "hi"; // Error! `MyOpaqueType` is not interchangable with `string`
+// ^^^^ Cannot assign "hi" to y because string is incompatible with MyOpaqueType
+```
+
+### Flow Enums
+
+[Flow Enums](../../enums) do not allow enum members with the same value, but which belong to different enums, to be used interchangeably.
+
+```js flow-check
+enum A {
+ X = "x",
+}
+enum B {
+ X = "x",
+}
+
+const a: A = B.X; // Error!
+```
diff --git a/_src/lang/refinements.md b/_src/lang/refinements.md
new file mode 100644
index 00000000000..1c198209a9f
--- /dev/null
+++ b/_src/lang/refinements.md
@@ -0,0 +1,284 @@
+---
+title: Type Refinements
+slug: /lang/refinements
+---
+
+Refinements allow us to narrow the type of a value based on conditional tests.
+
+For example, in the function below `value` is a [union](../../types/unions) of `"A"` or `"B"`.
+
+```js flow-check
+function func(value: "A" | "B") {
+ if (value === "A") {
+ value as "A";
+ }
+}
+```
+
+Inside of the `if` block we know that value must be `"A"` because that's the only
+time the if-statement will be true.
+
+The ability for a static type checker to be able to tell that the value inside
+the if statement must be `"A"` is known as a refinement.
+
+Next we'll add an `else` block to our if statement.
+
+```js flow-check
+function func(value: "A" | "B") {
+ if (value === "A") {
+ value as "A";
+ } else {
+ value as "B";
+ }
+}
+```
+
+Inside of the `else` block we know that value must be `"B"` because it can only
+be `"A"` or `"B"` and we've removed `"A"` from the possibilities.
+
+## Ways to refine in Flow
+
+### `typeof` checks
+You can use a `typeof value === ""` check to refine a value to one of the categories supported by the [`typeof`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) operator.
+
+The `typeof` operator can output `"undefined"`,`"boolean"`, `"number"`, `"bigint"`, `"string"`, `"symbol"`, `"function"`, or `"object"`.
+
+Keep in mind that the `typeof` operator will return `"object"` for objects, but also `null` and arrays as well.
+
+```js flow-check
+function func(value: mixed) {
+ if (typeof value === "string") {
+ value as string;
+ } else if (typeof value === "boolean") {
+ value as boolean;
+ } else if (typeof value === "object") {
+ // `value` could be null, an array, or an object
+ value as null | interface {} | $ReadOnlyArray;
+ }
+}
+```
+
+To check for `null`, use a `value === null` [equality](#equality-checks) check.
+
+```js flow-check
+function func(value: mixed) {
+ if (value === null) {
+ value as null; // `value` is null
+ }
+}
+```
+
+To check for [arrays](../../types/arrays), use `Array.isArray`:
+
+```js flow-check
+function func(value: mixed) {
+ if (Array.isArray(value)) {
+ value as $ReadOnlyArray; // `value` is an array
+ }
+}
+```
+
+### Equality checks
+
+As shown in the introductory example, you can use an equality check to narrow a value to a specific type.
+This also applies to equality checks made in `switch` statements.
+
+```js flow-check
+function func(value: "A" | "B" | "C") {
+ if (value === "A") {
+ value as "A";
+ } else {
+ value as "B" | "C";
+ }
+
+ switch (value) {
+ case "A":
+ value as "A";
+ break;
+ case "B":
+ value as "B";
+ break;
+ case "C":
+ value as "C";
+ break;
+ }
+}
+```
+
+While in general it is not recommended to use `==` in JavaScript, due to the coercions it performs,
+doing `value == null` (or `value != null`) checks `value` exactly for `null` and `void`.
+This works well with Flow's [maybe](../../types/maybe) types, which create a union with `null` and `void`.
+
+```js flow-check
+function func(value: ?string) {
+ if (value != null) {
+ value as string;
+ } else {
+ value as null | void;
+ }
+}
+```
+
+You can refine a union of object types based on a common tag, which we call [disjoint object unions](../../types/unions/#toc-disjoint-object-unions):
+
+```js flow-check
+type A = {type: "A", s: string};
+type B = {type: "B", n: number};
+
+function func(value: A | B) {
+ if (value.type === "A") {
+ // `value` is A
+ value.s as string; // Works
+ } else {
+ // `value` is B
+ value.n as number; // Works
+ }
+}
+```
+
+### Truthiness checks
+
+You can use non-booleans in JavaScript conditionals.
+`0`, `NaN`, `""`, `null`, and `undefined` will all coerce to `false` (and so are considered "falsey").
+Other values will coerce to `true` (and so are considered "truthy").
+
+```js flow-check
+function func(value: ?string) {
+ if (value) {
+ value as string; // Works
+ } else {
+ value as null | void; // Error! Could still be the empty string ""
+ }
+}
+```
+
+You can see in the above example why doing a truthy check when your value can be a string or number is not suggested:
+it is possible to unintentionally check against the `""` or `0`.
+We created a [Flow lint](../../linting) called [sketchy-null](../../linting/rule-reference/#toc-sketchy-null) to guard against this scenario:
+
+```js flow-check
+// flowlint sketchy-null:error
+function func(value: ?string) {
+ if (value) { // Error!
+ }
+}
+```
+
+### `instanceof` checks
+
+You can use the [instanceof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof) operator to narrow a value as well.
+It checks if the supplied constructor's prototype is anywhere in a value's prototype chain.
+
+```js flow-check
+class A {
+ amaze(): void {}
+}
+class B extends A {
+ build(): void {}
+}
+
+function func(value: mixed) {
+ if (value instanceof B) {
+ value.amaze(); // Works
+ value.build(); // Works
+ }
+
+ if (value instanceof A) {
+ value.amaze(); // Works
+ value.build(); // Error
+ }
+
+ if (value instanceof Object) {
+ value.toString(); // Works
+ }
+}
+```
+
+### Assignments
+
+Flow follows your control flow and narrows the type of a variable after you have assigned to it.
+
+```js flow-check
+declare const b: boolean;
+
+let x: ?string = b ? "str" : null;
+
+x as ?string;
+
+x = "hi";
+
+// We know `x` must now be a string after the assignment
+x as string; // Works
+```
+
+### Type Guards
+
+You can create a reusable refinement by defining a function which is a [type guard](../../types/type-guards/).
+
+```js flow-check
+function nonMaybe(x: ?T): x is T {
+ return x != null;
+}
+
+function func(value: ?string) {
+ if (nonMaybe(value)) {
+ value as string; // Works!
+ }
+}
+```
+
+## Refinement Invalidations {#toc-refinement-invalidations}
+
+It is also possible to invalidate refinements, for example:
+
+```js flow-check
+function otherFunc() { /* ... */ }
+
+function func(value: {prop?: string}) {
+ if (value.prop) {
+ otherFunc();
+ value.prop.charAt(0); // Error!
+ }
+}
+```
+
+The reason for this is that we don't know that `otherFunc()` hasn't done
+something to our value. Imagine the following scenario:
+
+```js flow-check
+const obj: {prop?: string} = {prop: "test"};
+
+function otherFunc() {
+ if (Math.random() > 0.5) {
+ delete obj.prop;
+ }
+}
+
+function func(value: {prop?: string}) {
+ if (value.prop) {
+ otherFunc();
+ value.prop.charAt(0); // Error!
+ }
+}
+
+func(obj);
+```
+
+Inside of `otherFunc()` we sometimes remove `prop`. Flow doesn't know if the
+`if (value.prop)` check is still true, so it invalidates the refinement.
+
+There's a straightforward way to get around this. Store the value before
+calling another function and use the stored value instead. This way you can
+prevent the refinement from invalidating.
+
+```js flow-check
+function otherFunc() { /* ... */ }
+
+function func(value: {prop?: string}) {
+ if (value.prop) {
+ const prop = value.prop;
+ otherFunc();
+ prop.charAt(0);
+ }
+}
+```
diff --git a/_src/lang/subtypes.md b/_src/lang/subtypes.md
new file mode 100644
index 00000000000..92f3af77ce8
--- /dev/null
+++ b/_src/lang/subtypes.md
@@ -0,0 +1,148 @@
+---
+title: Subsets & Subtypes
+slug: /lang/subtypes
+---
+
+## What is a subtype? {#toc-what-is-a-subtype}
+
+A type like `number`, `boolean`, or `string` describes a set of possible
+values. A `number` describes every possible number, so a single number
+(such as `42`) would be a *subtype* of the `number` type. Conversely, `number`
+would be a *supertype* of the type `42`.
+
+If we want to know whether one type is the subtype of another, we need to look at
+all the possible values for both types and figure out if the other has a
+_subset_ of the values.
+
+For example, if we had a `TypeA` which described the numbers 1 through 3
+(a [union](../../types/unions) of [literal types](../../types/literals)), and
+a `TypeB` which described the numbers 1 through 5: `TypeA` would be considered
+a _subtype_ of `TypeB`, because `TypeA` is a subset of `TypeB`.
+
+```js flow-check
+type TypeA = 1 | 2 | 3;
+type TypeB = 1 | 2 | 3 | 4 | 5;
+```
+
+Consider a `TypeLetters` which described the strings: "A", "B", "C", and a
+`TypeNumbers` which described the numbers: 1, 2, 3. Neither of them would
+be a subtype of the other, as they each contain a completely different set of
+values.
+
+```js flow-check
+type TypeLetters = "A" | "B" | "C";
+type TypeNumbers = 1 | 2 | 3;
+```
+
+Finally, if we had a `TypeA` which described the numbers 1 through 3, and a
+`TypeB` which described the numbers 3 through 5. Neither of them would be a
+subtype of the other. Even though they both have 3 and describe numbers, they
+each have some unique items.
+
+```js flow-check
+type TypeA = 1 | 2 | 3;
+type TypeB = 3 | 4 | 5;
+```
+
+## When are subtypes used? {#toc-when-are-subtypes-used}
+
+Most of the work that Flow does is comparing types against one another.
+
+For example, in order to know if you are calling a function correctly, Flow
+needs to compare the arguments you are passing with the parameters the
+function expects.
+
+This often means figuring out if the value you are passing in is a subtype of
+the value you are expecting.
+
+So if you write a function that expects the numbers 1 through 5, any subtype of
+that set will be acceptable.
+
+```js flow-check
+function f(param: 1 | 2 | 3 | 4 | 5) {
+ // ...
+}
+
+declare const oneOrTwo: 1 | 2; // Subset of the input parameters type.
+declare const fiveOrSix: 5 | 6; // Not a subset of the input parameters type.
+
+f(oneOrTwo); // Works!
+f(fiveOrSix); // Error!
+```
+
+## Subtypes of complex types {#toc-subtypes-of-complex-types}
+
+Flow needs to compare more than just sets of primitive values, it also needs to
+be able to compare objects, functions, and every other type that appears in the
+language.
+
+### Subtypes of objects {#toc-subtypes-of-objects}
+
+You can start to compare two objects by their keys. If one object contains all
+the keys of another object, then it may be a subtype.
+
+For example, if we had an `ObjectA` which contained the key `foo`, and an
+`ObjectB` which contained the keys `foo` and `bar`. Then it's possible that
+`ObjectB` is a subtype of `ObjectA`, if `ObjectA` is inexact.
+
+```js flow-check
+type ObjectA = {foo: string, ...};
+type ObjectB = {foo: string, bar: number};
+
+let objectB: ObjectB = {foo: 'test', bar: 42};
+let objectA: ObjectA = objectB; // Works!
+```
+
+But we also need to compare the types of the values. If both objects had a key
+`foo` but one was a `number` and the other was a `string`, then one would not
+be the subtype of the other.
+
+```js flow-check
+type ObjectA = {foo: string, ...};
+type ObjectB = {foo: number, bar: number};
+
+let objectB: ObjectB = { foo: 1, bar: 2 };
+let objectA: ObjectA = objectB; // Error!
+```
+
+If these values on the object happen to be other objects, we would have to
+compare those against one another. We need to compare every value
+recursively until we can decide if we have a subtype or not.
+
+### Subtypes of functions {#toc-subtypes-of-functions}
+
+Subtyping rules for functions are more complicated. So far, we've seen that `A`
+is a subtype of `B` if `B` contains all possible values for `A`. For functions,
+it's not clear how this relationship would apply. To simplify things, you can think
+of a function type `A` as being a subtype of a function type `B` if functions of type
+`A` can be used wherever a function of type `B` is expected.
+
+Let's say we have a function type and a few functions. Which of the functions can
+be used safely in code that expects the given function type?
+
+```js flow-check
+type FuncType = (1 | 2) => "A" | "B";
+
+declare function f1(1 | 2): "A" | "B" | "C";
+declare function f2(1 | null): "A" | "B";
+declare function f3(1 | 2 | 3): "A";
+
+f1 as FuncType; // Error
+f2 as FuncType; // Error
+f3 as FuncType; // Works!
+```
+
+- `f1` can return a value that `FuncType` never does, so code that relies on `FuncType`
+might not be safe if `f1` is used. Its type is not a subtype of `FuncType`.
+- `f2` can't handle all the argument values that `FuncType` does, so code that relies on
+`FuncType` can't safely use `f2`. Its type is also not a subtype of `FuncType`.
+- `f3` can accept all the argument values that `FuncType` does, and only returns
+values that `FuncType` does, so its type is a subtype of `FuncType`.
+
+In general, the function subtyping rule is this: a function type `B` is a subtype
+of a function type `A` if and only if `B`'s inputs are a superset of `A`'s, and `B`'s outputs
+are a subset of `A`'s. The subtype must accept _at least_ the same inputs as its parent,
+and must return _at most_ the same outputs.
+
+The decision of which direction to apply the subtyping rule on inputs and outputs is
+governed by [variance](../variance), which is the topic of the next section.
diff --git a/_src/lang/type-hierarchy.md b/_src/lang/type-hierarchy.md
new file mode 100644
index 00000000000..fa39415a8fd
--- /dev/null
+++ b/_src/lang/type-hierarchy.md
@@ -0,0 +1,122 @@
+---
+title: Type Hierarchy
+slug: /lang/type-hierarchy
+---
+
+Types in Flow form a hierarchy based on [subtyping](../subtypes):
+
+```mermaid
+graph BT
+
+mixed -.- any
+
+symbol --> mixed
+null --> mixed
+maybe["Maybe:
+ ?string"]
+maybe --> mixed
+null --> maybe
+void --> maybe
+void --> mixed
+string --> maybe
+string --> mixed
+
+union["Union:
+ number | bigint"]
+number --> union
+number --> mixed
+union --> mixed
+bigint --> mixed
+bigint --> union
+
+boolean --> mixed
+true --> boolean
+false --> boolean
+
+empty-interface["interface {}"] --> mixed
+some-interface["interface {prop: string}"] --> empty-interface
+someclass["class A {prop: string}"] --> some-interface
+inexact-empty-obj["Inexact empty object:
+ {...}"]
+inexact-empty-obj --> empty-interface
+inexact-some-obj["Inexact object:
+ {prop: string, ...}"] --> inexact-empty-obj
+inexact-some-obj --> some-interface
+exact-some-obj["Exact object:
+ {prop: string}"] --> inexact-some-obj
+exact-empty-obj["Exact empty object:
+ {}"]
+exact-empty-obj --> inexact-empty-obj
+roarray["$ReadOnlyArray<T>"] --> empty-interface
+tuple["Tuple:
+ [T, T]"]
+tuple --> roarray
+array["Array<T>"] --> roarray
+
+any-func["Function:
+ (...$ReadOnlyArray<empty>) => mixed"]
+any-func --> empty-interface
+some-func["(number) => boolean"] --> any-func
+some-func2["(string) => string"] --> any-func
+
+inter["Intersection:
+ (number => boolean) & (string => string)"]
+inter --> some-func
+inter --> some-func2
+
+empty --> inter
+empty --> null
+empty --> void
+empty --> true
+empty --> false
+empty --> exact-some-obj
+empty --> exact-empty-obj
+empty --> tuple
+empty --> array
+empty --> string
+empty --> number
+empty --> bigint
+empty --> someclass
+empty --> symbol
+any-bottom["any"] -.- empty
+
+click mixed "../../types/mixed"
+click any "../../types/any"
+click any-bottom "../../types/any"
+click empty "../../types/empty"
+click boolean "../../types/primitives/#toc-booleans"
+click number "../../types/primitives/#toc-numbers"
+click string "../../types/primitives/#toc-strings"
+click symbol "../../types/primitives/#toc-symbols"
+click bigint "../../types/primitives/#toc-bigints"
+click null "../../types/primitives/#toc-null-and-void"
+click void "../../types/primitives/#toc-null-and-void"
+click true "../../types/literals"
+click false "../../types/literals"
+click union "../../types/unions"
+click inter "../../types/intersections"
+click maybe "../../types/maybe"
+click array "../../types/arrays"
+click roarray "../../types/arrays/#toc-readonlyarray"
+click tuple "../../types/tuples"
+click someclass "../../types/classes"
+click empty-interface "../../types/interfaces"
+click some-interface "../../types/interfaces"
+click exact-some-obj "../../types/objects"
+click exact-empty-obj "../../types/objects"
+click inexact-some-obj "../../types/objects/#exact-and-inexact-object-types"
+click inexact-empty-obj "../../types/objects/#exact-and-inexact-object-types"
+click any-func "../../types/functions"
+click some-func "../../types/functions"
+click some-func2 "../../types/functions"
+
+classDef default fill:#eee, stroke:#000, stroke-width:1px
+```
+
+Click on a node to go to the documentation for that type.
+
+Types appearing higher in this graph are more general, while those appearing lower are more specific.
+An arrow pointing from type `A` to type `B` means that `A` is a subtype of `B`.
+For example, the type `string` is a subtype of `?string`.
+
+How can `any` be at both the top and the bottom? Because [it is unsafe](../../types/any/). This is denoted with a dotted line.
diff --git a/_src/lang/types-and-expressions.md b/_src/lang/types-and-expressions.md
new file mode 100644
index 00000000000..4a69aea5980
--- /dev/null
+++ b/_src/lang/types-and-expressions.md
@@ -0,0 +1,101 @@
+---
+title: Types & Expressions
+slug: /lang/types-and-expressions
+---
+
+In JavaScript there are many types of values: numbers, strings, booleans,
+functions, objects, and more.
+
+```js flow-check
+1234 as number;
+"hi" as string;
+true as boolean;
+[1, 2] as Array;
+({prop: "value"}) as {prop: string};
+(function func(s: string) {}) as string => void;
+```
+
+These values can be used in many different ways:
+
+```js flow-check
+1 + 2;
+"foo" + "bar";
+!true;
+[1, 2].push(3);
+const obj = {prop: "s"};
+let value = obj.prop;
+obj.prop = "value";
+function func(s: string) {}
+func("value");
+```
+
+All of these different expressions create a new type which is a result of the
+types of values and the operations run on them.
+
+```js flow-check
+let num: number = 1 + 2;
+let str: string = "foo" + "bar";
+```
+
+In Flow every value and expression has a type.
+
+## Figuring out types statically {#toc-figuring-out-types-statically}
+
+Flow needs a way to be able to figure out the type of every expression. But it
+can't just run your code to figure it out, if it did it would be affected by
+any issues that your code has. For example, if you created an infinite loop
+Flow would wait for it to finish forever.
+
+Instead, Flow needs to be able to figure out the type of a value by analyzing
+it without running it (static analysis). It works its way through every known
+type and starts to figure out what all the expressions around them result in.
+
+For example, to figure out the result of the following expression, Flow needs to
+figure out what its values are first.
+
+```js
+val1 + val2;
+```
+
+If the values are numbers, then the expression results in a number. If the
+values are strings, then the expression results in a string. There are a number
+of different possibilities here, so Flow must look up what the values are.
+
+If Flow is unable to figure out what the exact type is for each value, Flow
+must figure out what every possible value is and check to make sure that the
+code around it will still work with all of the possible types.
+
+## Soundness and Completeness {#toc-soundness-and-completeness}
+
+When you run your code, a single expression will only be run with a limited set
+of values. But still Flow checks _every_ possible value. In this way Flow is
+checking too many things or _over-approximating_ what will be valid code.
+
+By checking every possible value, Flow might catch errors that will not
+actually occur when the code is run. Flow does this in order to be _"sound"_.
+
+In type systems, ***soundness*** is the ability for a type checker to catch
+every single error that _might_ happen at runtime. This comes at the cost of
+sometimes catching errors that will not actually happen at runtime.
+
+On the flip-side, ***completeness*** is the ability for a type checker to only
+ever catch errors that _would_ happen at runtime. This comes at the cost of
+sometimes missing errors that will happen at runtime.
+
+In an ideal world, every type checker would be both sound _and_ complete so
+that it catches _every_ error that _will_ happen at runtime.
+
+Flow tries to be as sound and complete as possible. But because JavaScript was
+not designed around a type system, Flow sometimes has to make a tradeoff. When
+this happens Flow tends to favor soundness over completeness, ensuring that
+code doesn't have any bugs.
+
+Soundness is fine as long as Flow isn't being too noisy and preventing you from
+being productive. Sometimes when soundness would get in your way too much, Flow
+will favor completeness instead. There's only a handful of cases where Flow
+does this.
+
+Other type systems will favor completeness instead, only reporting real errors
+in favor of possibly missing errors. Unit/Integration testing is an extreme
+form of this approach. Often this comes at the cost of missing the errors that
+are the most complicated to find, leaving that part up to the developer.
diff --git a/_src/lang/types-first.md b/_src/lang/types-first.md
new file mode 100644
index 00000000000..a36addb8f6d
--- /dev/null
+++ b/_src/lang/types-first.md
@@ -0,0 +1,254 @@
+---
+title: File Signatures (Types-First)
+slug: /lang/types-first
+---
+
+Flow checks codebases by processing each file separately in dependency
+order. For every file containing important typing information for the checking
+process, a signature needs to be extracted and stored in
+main memory, to be used for files that depend on it. Flow relies on annotations
+available at the boundaries of files to build these signatures. We call this
+requirement of Flow's architecture *Types-First*.
+
+The benefit of this architecture is dual:
+
+1. It dramatically improves *performance*, in particular when it comes to
+rechecks. Suppose we want Flow to check a file `foo.js`, for which it hasn't
+checked its dependencies yet. Flow extracts the dependency signatures just by
+looking at the annotations around the exports. This process is mostly
+syntactic, and therefore much faster than full type inference that legacy versions
+of Flow (prior to v0.125) used to perform in order to generate signatures.
+
+2. It improves error *reliability*. Inferred types often become complicated, and may
+lead to errors being reported in downstream files, far away from their actual source.
+Type annotations at file boundaries of files can help localize such errors, and
+address them in the file that introduced them.
+
+The trade-off for this performance benefit is that exported parts of the code need to be
+annotated with types, or to be expressions whose type can be trivially inferred
+(for example numbers and strings).
+
+More information on the Types-First architecture can be found in [this post](https://medium.com/flow-type/types-first-a-scalable-new-architecture-for-flow-3d8c7ba1d4eb).
+
+## How to upgrade your codebase to Types-First {#toc-how-to-upgrade-your-codebase-to-types-first}
+
+> Note: Types-first has been the default mode since v0.134 and the only available
+mode since v0.143. No `.flowconfig` options are necessary to enable it since then.
+In case you're upgrading your codebase from a much earlier version here are some
+useful tools.
+
+### Upgrade Flow version {#toc-upgrade-flow-version}
+
+Types-first mode was officially released with version 0.125, but has been available in
+*experimental* status as of version 0.102. If you are currently on an older
+Flow version, you’d have to first upgrade Flow. Using the latest Flow version
+is the best way to benefit from the performance benefits outlined above.
+
+### Prepare your codebase for Types-First {#toc-prepare-your-codebase-for-types-first}
+
+Types-first requires annotations at module boundaries in order to build type
+signature for files. If these annotations are missing, then a `signature-verification-failure`
+is raised, and the exported type for the respective part of the code will be `any`.
+
+To see what types are missing to make your codebase types-first ready, add the
+following line to the `[options]` section of the `.flowconfig` file:
+
+```
+well_formed_exports=true
+```
+
+Consider for example a file `foo.js` that exports a function call to `foo`
+
+```js
+declare function foo(x: T): T;
+module.exports = foo(1);
+```
+
+The return type of function calls is currently not trivially inferable (due to
+features like polymorphism, overloading etc.). Their result needs to be annotated
+and so you’d see the following error:
+
+```
+Cannot build a typed interface for this module. You should annotate the exports
+of this module with types. Cannot determine the type of this call expression. Please
+provide an annotation, e.g., by adding a type cast around this expression.
+(`signature-verification-failure`)
+
+ 4│ module.exports = foo(1);
+ ^^^^^^
+```
+
+To resolve this, you can add an annotation like the following:
+
+```js
+declare function foo(x: T): T;
+module.exports = foo(1) as number;
+```
+
+> Note: As of version 0.134, types-first is the default mode. This mode automatically
+enables `well_formed_exports`, so you would see these errors without explicitly
+setting this flag. It is advisable to set `types_first=false` during this part of
+the upgrade.
+
+#### Seal your intermediate results {#toc-seal-your-intermediate-results}
+
+As you make progress adding types to your codebase, you can include directories
+so that they don’t regress as new code gets committed, and until the entire project
+has well-formed exports. You can do this by adding lines like the following to your
+.flowconfig:
+
+```
+well_formed_exports.includes=/path/to/directory
+```
+
+> Warning: That this is a *substring* check, not a regular expression (for performance
+reasons).
+
+
+#### A codemod for large codebases {#toc-a-codemod-for-large-codebases}
+
+
+Adding the necessary annotations to large codebases can be quite tedious. To ease
+this burden, we are providing a codemod based on Flow's inference, that can be
+used to annotate multiple files in bulk. See [this tutorial](../../cli/annotate-exports/) for more.
+
+
+### Enable the types-first flag {#toc-enable-the-types-first-flag}
+
+Once you have eliminated signature verification errors, you can turn on the types-first
+mode, by adding the following line to the `[options]` section of the `.flowconfig` file:
+
+```
+types_first=true
+```
+
+You can also pass `--types-first` to the `flow check` or `flow start` commands.
+
+The `well_formed_exports` flag from before is implied by `types_first`. Once
+this process is completed and types-first has been enabled, you can remove
+`well_formed_exports`.
+
+Unfortunately, it is not possible to enable types-first mode for part of your repo; this switch
+affects all files managed by the current `.flowconfig`.
+
+> Note: The above flags are available in versions of Flow `>=0.102` with the `experimental.`
+prefix (and prior to v0.128, it used `whitelist` in place of `includes`):
+```
+experimental.well_formed_exports=true
+experimental.well_formed_exports.whitelist=/path/to/directory
+experimental.types_first=true
+```
+
+> Note: If you are using a version where types-first is enabled by default (ie. `>=0.134`),
+make sure you set `types_first=false` in your .flowconfig while running the codemods.
+
+
+### Deal with newly introduced errors {#toc-deal-with-newly-introduced-errors}
+
+Switching between classic and types-first mode may cause some new Flow errors,
+besides signature-verification failures that we mentioned earlier. These errors
+are due differences in the way types based on annotations are interpreted, compared
+to their respective inferred types.
+
+Below are some common error patterns and how to overcome them.
+
+
+#### Array tuples treated as regular arrays in exports {#toc-array-tuples-treated-as-regular-arrays-in-exports}
+
+
+In types-first, an array literal in an *export position*
+
+```js
+module.exports = [e1, e2];
+```
+
+is treated as having type `Array`, where `e1` and `e2` have types `t1`
+and `t2`, instead of the tuple type `[t1, t2]`.
+
+In classic mode, the inferred type encompassed both types at the same time. This
+might cause errors in importing files that expect for example to find type `t1`
+in the first position of the import.
+
+**Fix:** If a tuple type is expected, then the annotation `[t1, t2]` needs to be
+explicitly added on the export side.
+
+#### Indirect object assignments in exports {#toc-indirect-object-assignments-in-exports}
+
+
+Flow allows the code
+
+```js
+function foo(): void {}
+foo.x = () => {};
+foo.x.y = 2;
+module.exports = foo;
+```
+
+but in types-first the exported type will be
+
+```plaintext
+{
+ (): void;
+ x: () => void;
+}
+```
+
+In other words it won’t take into account the update on `y`.
+
+**Fix:** To include the update on `y` in the exported type, the export will need
+to be annotated with the type
+
+```plaintext
+{
+ (): void;
+ x: { (): void; y: number; };
+};
+```
+
+The same holds for more complex assignment patterns like
+
+```js
+function foo(): void {}
+Object.assign(foo, { x: 1});
+module.exports = foo;
+```
+
+where you’ll need to manually annotate the export with `{ (): void; x: number }`,
+or assignments preceding the function definition
+
+```js
+foo.x = 1;
+function foo(): void {}
+module.exports = foo;
+```
+
+Note that in the last example, Flow types-first will pick up the static update if
+it was after the definition:
+
+```js
+function foo(): void {}
+foo.x = 1;
+module.exports = foo;
+```
+
+### Exported variables with updates {#toc-exported-variables-with-updates}
+
+The types-first signature extractor will not pick up subsequent update of an exported
+let-bound variables. Consider the example
+
+```js
+let foo: number | string = 1;
+foo = "blah";
+module.exports = foo;
+```
+
+In classic mode the exported type would be `string`. In types-first it will be
+`number | string`, so if downstream typing depends on the more precise type, then
+you might get some errors.
+
+**Fix:** Introduce a new variable on the update and export that one. For example
+```js
+const foo1: number | string = 1;
+const foo2 = "blah";
+module.exports = foo2;
+```
diff --git a/_src/lang/variables.md b/_src/lang/variables.md
new file mode 100644
index 00000000000..477b3be40d2
--- /dev/null
+++ b/_src/lang/variables.md
@@ -0,0 +1,209 @@
+---
+title: Variable Declarations
+slug: /lang/variables
+---
+
+import {SinceVersion} from '../../components/VersionTags';
+
+When you are declaring a new variable, you may optionally declare its type.
+
+JavaScript has three ways of declaring local variables:
+
+- `var` - declares a variable, optionally assigning a value.
+ ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var))
+- `let` - declares a block-scoped variable, optionally assigning a value.
+ ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let))
+- `const` - declares a block-scoped variable, assigning a value that cannot be re-assigned.
+ ([MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const))
+
+In Flow these fall into two groups:
+
+- `let` and `var` - variables that **can** be reassigned.
+- `const` - variables that **cannot** be reassigned.
+
+```js flow-check
+var varVariable = 1;
+let letVariable = 1;
+const constVariable = 1;
+
+varVariable = 2; // Works!
+letVariable = 2; // Works!
+constVariable = 2; // Error!
+```
+
+## `const` {#toc-const}
+
+Since a `const` variable cannot be re-assigned at a later time it is fairly
+simple.
+
+Flow can either infer the type from the value you are assigning to it or you
+can provide it with a type.
+
+```js flow-check
+const foo /* : number */ = 1;
+const bar: number = 2;
+```
+
+## `var` and `let` {#toc-var-and-let}
+Since `var` and `let` can be re-assigned, there's a few more rules you'll need
+to know about.
+
+When you provide a type, you will be able to re-assign the value, but it must
+always be of a compatible type.
+
+```js flow-check
+let foo: number = 1;
+foo = 2; // Works!
+foo = "3"; // Error!
+```
+
+When the variable has no annotation, Flow infers a precise type based on
+ their initializer or initial assignment. All subsequent assignments
+to that variable will be constrained by this type. This section shows some examples
+of how Flow determines what type an unannotated variable is inferred to have.
+
+
+**If you want a variable to have a different type than what Flow infers for it,
+you can always add a type annotation to the variable’s declaration. That will
+override everything discussed in this page!**
+
+### Variables initialized at their declarations {#toc-variables-initialized-at-their-declarations}
+
+The common case for unannotated variables is very straightforward: when a
+variable is declared with an initializer that is not the literal `null`, that
+variable will from then on have the type of the initializer, and future writes
+to the variable will be constrained by that type.
+
+```js flow-check
+import * as React from 'react';
+
+type Props = $ReadOnly<{ prop: string }>;
+
+declare var x: number;
+declare var y: number;
+declare var props: Props;
+
+let product = Math.sqrt(x) + y;
+// `product` has type `number`
+
+let Component = ({prop}: Props): React.Node => { return }
+// `Component` has type`React.ComponentType`
+
+let element =
+// `element` has type `React.Element>`
+
+/* Let's define a new component */
+
+type OtherProps = $ReadOnly<{ ...Props, extra_prop: number }>;
+declare var OtherComponent: (OtherProps) => React.Node;
+declare var other_props: OtherProps
+
+/* Any subsequent assignments to `product`, `Component`, or `element` will be
+ * checked against the types that Flow infers for the initializers, and if
+ * conflicting types are assigned, Flow will signal an error. */
+
+product = "Our new product is...";
+Component = ({prop}: OtherProps): React.Node => { return };
+element = ;
+```
+
+If you want these examples to typecheck, and for Flow to realize that different
+kinds of values can be written to these variables, you must add a type
+annotation reflecting this more general type to their declarations:
+```js
+let product: number | string = ...
+let Component: mixed = ... // No good type to represent this! Consider restructuring
+let element: React.Node = ...
+```
+### Variables declared without initializers {#toc-variables-declared-without-initializers}
+
+Often variables are declared without initializers. In such cases, Flow will try
+to choose the "first" assignment or assignments to the variable to define its
+type. "First" here means both top-to-bottom and nearer-scope to
+deeper-scope—we’ll try to choose an assignment that happens in the same function
+scope as the variable’s declaration, and only look inside nested functions if we
+don’t find any assignments locally:
+```js flow-check
+let topLevelAssigned;
+function helper() {
+ topLevelAssigned = 42; // Error: `topLevelAssigned` has type `string`
+}
+topLevelAssigned = "Hello world"; // This write determines the var's type
+topLevelAssigned = true; // Error: `topLevelAssigned` has type `string`
+```
+If there are two or more possible "first assignments," due to an `if`- or
+`switch`-statement, they’ll both count—this is one of the few ways that Flow
+will still infer unions for variable types:
+```js flow-check
+let myNumberOrString;
+declare var condition: boolean;
+if (condition) {
+ myNumberOrString = 42; // Determines type
+} else {
+ myNumberOrString = "Hello world"; // Determines type
+}
+myNumberOrString = 21; // fine, compatible with type
+myNumberOrString = "Goodbye"; // fine, compatible with type
+myNumberOrString = false; // Error: `myNumberOrString` has type `number | string`
+```
+This only applies when the variable is written to in both branches, however. If
+only one branch contains a write, that write becomes the type of the variable
+afterwards (though Flow will still check to make sure that the variable is
+definitely initialized):
+
+```js flow-check
+let oneBranchAssigned;
+declare var condition: boolean;
+if (condition) {
+ oneBranchAssigned = "Hello world!";
+}
+oneBranchAssigned.toUpperCase(); // Error: `oneBranchAssigned` may be uninitialized
+oneBranchAssigned = 42; // Error: `oneBranchAssigned` has type `string`
+```
+### Variables initialized to `null` {#toc-variables-initialized-to-null}
+
+Finally, the one exception to the general principle that variable’s types are
+determined by their first assignment(s) is when a variable is initialized as (or
+whose first assignment is) the literal value `null`. In such cases, the *next*
+non-null assignment (using the same rules as above) determines the rest of the
+variable’s type, and the overall type of the variable becomes a union of `null`
+and the type of the subsequent assignment. This supports the common pattern
+where a variable starts off as `null` before getting assigned by a value of some
+other type:
+```js flow-check
+function findIDValue(dict: {[key: string]: T}): T {
+ let idVal = null; // initialized as `null`
+ for (const key in dict) {
+ if (key === 'ID') {
+ idVal = dict[key]; // Infer that `idVal` has type `null | T`
+ }
+ }
+ if (idVal === null) {
+ throw new Error("No entry for ID!");
+ }
+ return idVal;
+}
+```
+
+## Catch variables
+If a `catch` variable does not have an annotation, its default type is [`any`](../../types/any).
+
+You can optionally annotate it with exactly [`mixed`](../../types/mixed) or `any`. E.g.
+
+```js flow-check
+try {
+} catch (e: mixed) {
+ if (e instanceof TypeError) {
+ e as TypeError; // OK
+ } else if (e instanceof Error) {
+ e as Error; // OK
+ } else {
+ throw e;
+ }
+}
+```
+
+By using `mixed`, you can improve your safety and Flow [coverage](../../cli/coverage/),
+at the trade-off of increased runtime checks.
+
+You can change the default type of `catch` variables when there is no annotation by setting the [`use_mixed_in_catch_variables`](../../config/options/#toc-use-mixed-in-catch-variables) option to true.
diff --git a/_src/lang/variance.md b/_src/lang/variance.md
new file mode 100644
index 00000000000..be16a6a8701
--- /dev/null
+++ b/_src/lang/variance.md
@@ -0,0 +1,144 @@
+---
+title: Type Variance
+slug: /lang/variance
+---
+
+Variance is a topic that comes up fairly often in type systems. It is used to determine
+how type parameters behave with respect to subtyping.
+
+First we'll setup a couple of classes that extend one another.
+
+```js
+class Noun {}
+class City extends Noun {}
+class SanFrancisco extends City {}
+```
+
+We saw in the section on [generic types](../../types/generics/#toc-variance-sigils)
+that it is possible to
+use variance sigils to describe when a type parameter is used in an output position,
+when it is used in an input position, and when it is used in either one.
+
+Here we'll dive deeper into each one of these cases.
+
+## Covariance {#toc-covariance}
+
+Consider for example the type
+```js
+type CovariantOf = {
+ +prop: X;
+ getter(): X;
+}
+```
+Here, `X` appears strictly in *output* positions: it is used to read out information
+from objects `o` of type `CovariantOf`, either through property accesses `o.prop`,
+or through calls to `o.getter()`.
+
+Notably, there is no way to input data through the reference to the object `o`,
+given that `prop` is a readonly property.
+
+When these conditions hold, we can use the sigil `+` to annotate `X` in the definition
+of `CovariantOf`:
+```js
+type CovariantOf<+X> = {
+ +prop: X;
+ getter(): X;
+}
+```
+
+These conditions have important implications on the way that we can treat an object
+of type `CovariantOf` with respect to subtyping. As a reminder, subtyping rules
+help us answer the question: "given some context that expects values of type
+`T`, is it safe to pass in values of type `S`?" If this is the case, then `S` is a
+subtype of `T`.
+
+Using our `CovariantOf` definition, and given that `City` is a subtype of `Noun`, it is
+also the case that `CovariantOf` is a subtype of `CovariantOf`. Indeed
+* it is safe to *read* a property `prop` of type `City` when a property
+of type `Noun` is expected, and
+* it is safe to *return* values of type `City` when calling `getter()`, when
+values of type `Noun` are expected.
+
+Combining these two, it will always be safe to use `CovariantOf` whenever a
+`CovariantOf` is expected.
+
+A commonly used example where covariance is used is [`$ReadOnlyArray`](../../types/arrays/#toc-readonlyarray).
+Just like with the `prop` property, one cannot use a `$ReadOnlyArray` reference to write data
+to an array. This allows more flexible subtyping rules: Flow only needs to prove that
+`S` is a subtype of `T` to determine that `$ReadOnlyArray` is also a subtype
+of `$ReadOnlyArray`.
+
+
+## Invariance {#toc-invariance}
+
+Let's see what happens if we try to relax the restrictions on the use of `X` and make,
+for example, `prop` be a read-write property. We arrive at the type definition
+```js
+type NonCovariantOf = {
+ prop: X;
+ getter(): X;
+};
+```
+Let's also declare a variable `nonCovariantCity` of type `NonCovariantOf`
+```js
+declare const nonCovariantCity: NonCovariantOf;
+```
+Now, it is not safe to consider `nonCovariantCity` as an object of type `NonCovariantOf`.
+Were we allowed to do this, we could have the following declaration:
+```js
+const nonCovariantNoun: NonCovariantOf = nonCovariantCity;
+```
+This type permits the following assignment:
+```js
+nonCovariantNoun.prop = new Noun;
+```
+which would invalidate the original type for `nonCovariantCity` as it would now be storing
+a `Noun` in its `prop` field.
+
+
+What distinguishes `NonCovariantOf` from the `CovariantOf` definition is that type parameter `X` is used both
+in input and output positions, as it is being used to both read and write to
+property `prop`. Such a type parameter is called *invariant* and is the default case
+of variance, thus requiring no prepending sigil:
+```js
+type InvariantOf = {
+ prop: X;
+ getter(): X;
+ setter(X): void;
+};
+```
+Assuming a variable
+```js
+declare const invariantCity: InvariantOf;
+```
+it is *not* safe to use `invariantCity` in a context where:
+- an `InvariantOf` is needed, because we should not be able to write a `Noun` to property
+`prop`.
+- an `InvariantOf` is needed, because reading `prop` could return a `City` which
+may not be `SanFrancisco`.
+
+In orther words, `InvariantOf` is neither a subtype of `InvariantOf` nor
+a subtype of `InvariantOf`.
+
+
+## Contravariance {#toc-contravariance}
+
+When a type parameter is only used in *input* positions, we say that it is used in
+a *contravariant* way. This means that it only appears in positions through which
+we write data to the structure. We use the sigil `-` to describe this kind of type
+parameters:
+
+```js
+type ContravariantOf<-X> = {
+ -prop: X;
+ setter(X): void;
+};
+```
+Common contravariant positions are write-only properties and "setter" functions.
+
+An object of type `ContravariantOf` can be used whenever an object of type
+`ContravariantOf` is expected, but not when a `ContravariantOf` is.
+In other words, `ContravariantOf` is a subtype of `ContravariantOf`, but not
+`ContravariantOf`.
+This is because it is fine to write `SanFrancisco` into a property that can have any `City` written
+to, but it is not safe to write just any `Noun`.
diff --git a/_src/lang/width-subtyping.md b/_src/lang/width-subtyping.md
new file mode 100644
index 00000000000..efaf18eb6d8
--- /dev/null
+++ b/_src/lang/width-subtyping.md
@@ -0,0 +1,65 @@
+---
+title: Width Subtyping
+slug: /lang/width-subtyping
+---
+
+It's safe to use an object with "extra" properties in a position that is
+annotated with a specific set of properties, if that object type is [inexact](../../types/objects/#exact-and-inexact-object-types).
+
+```js flow-check
+function func(obj: {foo: string, ...}) {
+ // ...
+}
+
+func({
+ foo: "test", // Works!
+ bar: 42 // Works!
+});
+```
+
+Within `func`, we know that `obj` has at least a property `foo` and the
+property access expression `obj.foo` will have type `string`.
+
+This is a kind of subtyping commonly referred to as "width subtyping" because
+a type that is "wider" (i.e., has more properties) is a subtype of a
+narrower type.
+
+So in the following example, `obj2` is a _subtype_ of `obj1`.
+
+```js flow-check
+let obj1: {foo: string, ...} = {foo: 'test'};
+let obj2 = {foo: 'test', bar: 42};
+obj2 as {foo: string, ...};
+```
+
+However, it's often useful to know that a property is definitely absent.
+
+```js flow-check
+function func(obj: {foo: string, ...} | {bar: number, ...}) {
+ if (obj.foo) {
+ obj.foo as string; // Error!
+ }
+}
+```
+
+The above code has a type error because Flow would also allow the call
+expression `func({foo: 1, bar: 2})`, because `{foo: number, bar: number}`
+is a subtype of `{bar: number, ...}`, one of the members of the parameter's union
+type.
+
+For cases like this where it's useful to assert the absence of a property,
+You can use [exact object types](../../types/objects/#exact-and-inexact-object-types).
+
+```js flow-check
+function func(obj: {foo: string} | {bar: number}) {
+ if (obj.foo) {
+ obj.foo as string; // Works!
+ }
+}
+```
+
+[Exact object types](../../types/objects/#exact-and-inexact-object-types) disable width
+subtyping, and do not allow additional properties to exist.
+
+Using exact object types lets Flow know that no extra properties will exist at
+runtime, which allows [refinements](../refinements/) to get more specific.
diff --git a/_src/libdefs/creation.md b/_src/libdefs/creation.md
new file mode 100644
index 00000000000..7e2554404c9
--- /dev/null
+++ b/_src/libdefs/creation.md
@@ -0,0 +1,199 @@
+---
+title: Creating Library Definitions
+slug: /libdefs/creation
+---
+
+Before spending the time to write your own libdef, we recommend that you look to
+see if there is already a libdef for the third-party code that you're addressing.
+`flow-typed` is a [tool and repository](https://github.com/flowtype/flow-typed/)
+for sharing common libdefs within the Flow community -- so it's a good way to
+knock out a good chunk of any public libdefs you might need for your project.
+
+However sometimes there isn't a pre-existing libdef or you have third-party
+code that isn't public and/or you really just need to write a libdef yourself.
+To do this you'll start by creating a `.js` file for each libdef you're going to
+write and put them in the `/flow-typed` directory at the root of your project.
+In these libdef file(s) you'll use a special set of Flow syntax (explained
+below) to describe the interfaces of the relevant third-party code.
+
+## Declaring A Global Function {#toc-declaring-a-global-function}
+
+To declare a global function that should be accessible throughout your project,
+use the `declare function` syntax in a libdef file:
+
+**flow-typed/myLibDef.js**
+```js flow-check
+declare function foo(a: number): string;
+```
+
+This tells Flow that any code within the project can reference the
+`foo` global function, and that the function takes one argument (a `number`) and
+it returns a `string`.
+
+## Declaring A Global Class {#toc-declaring-a-global-class}
+
+To declare a global class that should be accessible throughout your project,
+use the `declare class` syntax in a libdef file:
+
+**flow-typed/myLibDef.js**
+```js flow-check
+declare class URL {
+ constructor(urlStr: string): URL;
+ toString(): string;
+
+ static compare(url1: URL, url2: URL): boolean;
+}
+```
+
+This tells Flow that any code within the project can reference the `URL` global
+class. Note that this class definition does not have any implementation details
+-- it exclusively defines the interface of the class.
+
+## Declaring A Global Variable {#toc-declaring-a-global-variable}
+
+To declare a global variable that should be accessible throughout your project,
+use the `declare var`, `declare let`, or `declare const` syntax in a libdef file:
+
+**flow-typed/myLibDef.js**
+```js flow-check
+declare const PI: number;
+```
+
+This tells Flow that any code within the project can reference the `PI` global
+variable -- which, in this case, is a `number`.
+
+## Declaring A Global Type {#toc-declaring-a-global-type}
+
+To declare a global type that should be accessible throughout your project,
+use the `declare type` syntax in a libdef file:
+
+**flow-typed/myLibDef.js**
+```js flow-check
+declare type UserID = number;
+```
+
+This tells Flow that any code within the project can reference the `UserID`
+global type -- which, in this case, is just an alias for `number`.
+
+## Declaring A Module {#toc-declaring-a-module}
+
+Often, third-party code is organized in terms of modules rather than globals. To
+write a libdef that declares the presence of a module you'll want to use the
+`declare module` syntax:
+
+```js
+declare module "some-third-party-library" {
+ // This is where we'll list the module's exported interface(s)
+}
+```
+
+The name specified in quotes after `declare module` can be any string, but it
+should correspond to the same string you'd use to `require` or `import` the
+third-party module into your project. For defining modules that are accessed via
+a relative `require`/`import` path, please see the docs on the [`.flow` files](../../declarations)
+
+Within the body of a `declare module` block, you can specify the set of exports
+for that module. However, before we start talking about exports we have to talk
+about the two kinds of modules that Flow supports: CommonJS and ES modules.
+
+Flow can handle both CommonJS and ES modules, but there are some relevant
+differences between the two that need to be considered when using
+`declare module`.
+
+#### Declaring An ES Module {#toc-declaring-an-es-module}
+
+[ES modules](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export)
+have two kinds of exports: A **named** export and a **default** export. Flow supports the ability
+to declare either or both of these kinds of exports within a `declare module` body as follows:
+
+###### Named Exports {#toc-named-exports}
+
+**flow-typed/some-es-module.js**
+```js
+declare module "some-es-module" {
+ // Declares a named "concatPath" export
+ declare export function concatPath(dirA: string, dirB: string): string;
+}
+```
+
+Note that you can also declare other things inside the body of the
+`declare module`, and those things will be scoped to the body of the
+`declare module` -- **but they will not be exported from the module**:
+
+**flow-typed/some-es-module.js**
+```js
+declare module "some-es-module" {
+ // Defines the type of a Path class within this `declare module` body, but
+ // does not export it. It can only be referenced by other things inside the
+ // body of this `declare module`
+ declare class Path {
+ toString(): string;
+ }
+
+ // Declares a named "concatPath" export which returns an instance of the
+ // `Path` class (defined above)
+ declare export function concatPath(dirA: string, dirB: string): Path;
+}
+```
+
+###### Default Exports {#toc-default-exports}
+
+**flow-typed/some-es-module.js**
+```js
+declare module "some-es-module" {
+ declare class URL {
+ constructor(urlStr: string): URL;
+ toString(): string;
+
+ static compare(url1: URL, url2: URL): boolean;
+ }
+
+ // Declares a default export whose type is `typeof URL`
+ declare export default typeof URL;
+}
+```
+
+It is also possible to declare both **named** and **default** exports in the
+same `declare module` body.
+
+#### Declaring A CommonJS Module {#toc-declaring-a-commonjs-module}
+
+CommonJS modules have a single value that is exported (the `module.exports`
+value). To describe the type of this single value within a `declare module`
+body, you'll use the `declare module.exports` syntax:
+
+**flow-typed/some-commonjs-module.js**
+```js
+declare module "some-commonjs-module" {
+ // The export of this module is an object with a "concatPath" method
+ declare module.exports: {
+ concatPath(dirA: string, dirB: string): string;
+ };
+}
+```
+
+Note that you can also declare other things inside the body of the
+`declare module`, and those things will be scoped to the body of the
+`declare module`, **but they will not be exported from the module**:
+
+**flow-typed/some-commonjs-module.js**
+```js
+declare module "some-commonjs-module" {
+ // Defines the type of a Path class within this `declare module` body, but
+ // does not export it. It can only be referenced by other things inside the
+ // body of this `declare module`
+ declare class Path {
+ toString(): string;
+ }
+
+ // The "concatPath" function now returns an instance of the `Path` class
+ // (defined above).
+ declare module.exports: {
+ concatPath(dirA: string, dirB: string): Path
+ };
+}
+```
+
+NOTE: Because a given module cannot be both an ES module and a CommonJS module,
+ it is an error to mix `declare export [...]` with
+ `declare module.exports: ...` in the same `declare module` body.
diff --git a/_src/libdefs/index.md b/_src/libdefs/index.md
new file mode 100644
index 00000000000..c4be1c5b6d0
--- /dev/null
+++ b/_src/libdefs/index.md
@@ -0,0 +1,46 @@
+---
+title: Library Definitions
+slug: /libdefs
+description: Learn how to create and use library definitions for the third-party code your code depends on.
+---
+
+## What's a "Library Definition"? {#toc-what-s-a-library-definition}
+
+Most real JavaScript programs depend on third-party code and not just code
+immediately under the control of the project. That means a project using Flow
+may need to reference outside code that either doesn't have type information or
+doesn't have accurate and/or precise type information. In order to handle this,
+Flow supports the concept of a "library definition" (a.k.a. "libdef").
+
+A libdef is a special file that informs Flow about the type signature of some
+specific third-party module or package of modules that your application uses.
+If you're familiar with languages that have header files (like `C++`), you can
+think of libdefs as a similar concept.
+
+These special files use the same `.js` extension as normal JS code, but they are
+placed in a directory called `flow-typed` in the root directory of your project.
+Placement in this directory tells Flow to interpret them as libdefs rather than
+normal JS files.
+
+> NOTE: Using the `/flow-typed` directory for libdefs is a convention that
+> enables Flow to JustWork™ out of the box and encourages consistency
+> across projects that use Flow, but it is also possible to explicitly
+> configure Flow to look elsewhere for libdefs using the [`[libs]` section
+> of your `.flowconfig`](../config/libs).
+
+You can also learn about [declaration files](../declarations).
+
+## General Best Practices {#toc-general-best-practices}
+
+**Try to provide a libdef for each third-party library your project uses.**
+
+If a third-party library that has no type information is used by your project,
+Flow will treat it like any other untyped dependency and mark all of its exports
+as `any`.
+
+Because of this behavior, it is a best practice to find or write libdefs for as
+many of the third-party libraries that you use as you can. We recommend checking
+out the `flow-typed`
+[tool and repository](https://github.com/flow-typed/flow-typed/)
+, which helps you quickly find and install pre-existing libdefs for your
+third-party dependencies.
diff --git a/_src/linting/flowlint-comments.md b/_src/linting/flowlint-comments.md
new file mode 100644
index 00000000000..ff8eee30a2e
--- /dev/null
+++ b/_src/linting/flowlint-comments.md
@@ -0,0 +1,82 @@
+---
+title: Flowlint Comments
+slug: /linting/flowlint-comments
+---
+
+You can use `flowlint` comments to specify more granular lint settings within a file.
+These comments come in three froms:
+* [flowlint](#toc-flowlint)
+* [flowlint-line](#toc-flowlint-line)
+* [flowlint-next-line](#toc-flowlint-next-line)
+
+In all forms, whitespace and asterisks between words are ignored, allowing for flexible formatting.
+
+### flowlint {#toc-flowlint}
+The basic `flowlint` comment takes a comma-delimited list of `rule:severity` pairs and
+applies those settings for the rest of the source file until overridden. This has
+three primary purposes: applying settings over a block, applying settings over a file,
+and applying settings over part of a line.
+
+**settings over a block of code:**
+A pair of `flowlint` comments can be used to apply a certain setting over a block of code.
+For example, to disable the untyped-type-import lint over a block of type imports would look like this:
+```js
+import type {
+ // flowlint untyped-type-import:off
+ Foo,
+ Bar,
+ Baz,
+ // flowlint untyped-type-import:error
+} from './untyped.js';
+```
+
+**settings over a file:**
+A `flowlint` comment doesn't have to have a matching comment to form a block.
+An unmatched comment simply applies its settings to the rest of the file. You
+could use this, for example, to suppress all sketchy-null-check lints in a particular file:
+```js
+// flowlint sketchy-null:off
+...
+```
+
+**settings over part of a line:**
+The settings applied by `flowlint` start and end right at the comment itself. This
+means that you can do things like
+```js
+function foo(a: ?boolean, b: ?boolean) {
+ if (/* flowlint sketchy-null-bool:off */a/* flowlint sketchy-null-bool:warn */ && b) {
+ ...
+ } else {
+ ...
+ }
+}
+```
+if you want control at an even finer level than you get from the line-based comments.
+
+### flowlint-line {#toc-flowlint-line}
+A `flowlint-line` comment works similarly to a `flowlint` comment, except it only
+applies its settings to the current line instead of applying them for the rest of the file.
+The primary use for `flowlint-line` comments is to suppress a lint on a particular line:
+```js
+function foo(x: ?boolean) {
+ if (x) { // flowlint-line sketchy-null-bool:off
+ ...
+ } else {
+ ...
+ }
+}
+```
+
+
+### flowlint-next-line {#toc-flowlint-next-line}
+`flowlint-next-line` works the same as `flowlint-line`, except it applies its settings to the next line instead of the current line:
+```js
+function foo(x: ?boolean) {
+ // flowlint-next-line sketchy-null-bool:off
+ if (x) {
+ ...
+ } else {
+ ...
+ }
+}
+```
diff --git a/_src/linting/index.md b/_src/linting/index.md
new file mode 100644
index 00000000000..d1f0df52c20
--- /dev/null
+++ b/_src/linting/index.md
@@ -0,0 +1,80 @@
+---
+title: Linting Overview
+slug: /linting
+description: Learn how to configure Flow's linter to find potentially harmful code.
+---
+
+Flow contains a linting framework that can tell you about more than just type errors. This framework is highly configurable in order to show you the information you want and hide the information you don't.
+
+### Configuring Lints in the `.flowconfig` {#toc-configuring-lints-in-the-flowconfig}
+
+Lint settings can be specified in the `[lints]` section of the `.flowconfig` as a list of `rule=severity` pairs. These settings apply globally to the entire project.
+
+```
+[lints]
+all=warn
+untyped-type-import=error
+sketchy-null-bool=off
+```
+
+### Configuring Lints from the CLI {#toc-configuring-lints-from-the-cli}
+
+Lint settings can be specified using the `--lints` flag of a Flow server command as a comma-delimited list of `rule=severity` pairs. These settings apply globally to the entire project.
+
+```
+flow start --lints "all=warn, untyped-type-import=error, sketchy-null-bool=off"
+```
+
+### Configuring Lints with Comments {#toc-configuring-lints-with-comments}
+
+Lint settings can be specified inside a file using `flowlint` comments. These
+settings apply to a region of a file, or a single line, or part of a line. For
+more details see [Flowlint Comments](./flowlint-comments).
+
+```js flow-check
+// flowlint sketchy-null:error
+const x: ?number = 0;
+
+if (x) {} // Error
+
+// flowlint-next-line sketchy-null:off
+if (x) {} // No Error
+
+if (x) {} /* flowlint-line sketchy-null:off */ // No Error
+
+// flowlint sketchy-null:off
+if (x) {} // No Error
+if (x) {} // No Error
+```
+
+### Lint Settings Precedence {#toc-lint-settings-precedence}
+
+Lint settings in `flowlint` comments have the highest priority, followed by lint rules in the `--lints` flag, followed by the `.flowconfig`.
+This order allows you to use `flowlint` comments for fine-grained linting control, the `--lints` flag for trying out new lint settings, and the `.flowconfig` for stable project-wide settings.
+
+Within the `--lints` flag and the `.flowconfig`, rules lower down override rules higher up, allowing you to write things like
+```
+[lints]
+# warn on all sketchy-null checks
+sketchy-null=warn
+# ... except for booleans
+sketchy-null-bool=off
+```
+
+The lint settings parser is fairly intelligent and will stop you if you write a redundant rule, a rule that gets completely overwritten, or an unused flowlint suppression. This should prevent most accidental misconfigurations of lint rules.
+
+### Severity Levels and Meanings {#toc-severity-levels-and-meanings}
+
+**off:**
+The lint is ignored. Setting a lint to `off` is similar to suppressing a type error with a suppression comment, except with much more granularity.
+
+**warn:**
+Warnings are a new severity level introduced by the linting framework. They are treated differently than errors in a couple of ways:
+* Warnings don't affect the exit code of Flow. If Flow finds warnings but no errors, it still returns 0.
+* Warnings aren't shown on the CLI by default, to avoid spew. CLI warnings can be
+ enabled by passing the `--include-warnings` flag to the Flow server or the
+ Flow client, or by setting `include_warnings=true` in the `.flowconfig`.
+ This is good for smaller projects that want to see all project warnings at once.
+
+**error:**
+Lints with severity `error` are treated exactly the same as any other Flow error.
diff --git a/_src/linting/rule-reference.md b/_src/linting/rule-reference.md
new file mode 100644
index 00000000000..fb58f6c7446
--- /dev/null
+++ b/_src/linting/rule-reference.md
@@ -0,0 +1,232 @@
+---
+title: Lint Rule Reference
+slug: /linting/rule-reference
+---
+
+### `all` {#toc-all}
+While `all` isn't technically a lint rule, it's worth mentioning here. `all` sets the default
+level for lint rules that don't have a level set explicitly. `all` can only
+occur as the first entry in a `.flowconfig` or as the first rule in a `--lints`
+flag. It's not allowed in comments at all because it would have different
+semantics than would be expected.
+
+### `ambiguous-object-type` {#toc-ambiguous-object-type}
+Triggers when you use object type syntax without explicitly specifying exactness or inexactness.
+
+This lint setting is ignored when [`exact_by_default`](../../config/options/#toc-exact-by-default) is set to `false`.
+
+```js flow-check
+// flowlint ambiguous-object-type:error
+
+type A = {x: number}; // Error
+type B = {x: number, ...} // Ok
+type C = {| x: number |} // Ok
+```
+
+### `deprecated-type` {#toc-deprecated-type}
+Triggered on the `bool` type, which is just an alias for `boolean`. Just use `boolean` instead.
+
+```js flow-check
+// flowlint deprecated-type:error
+
+type A = Array; // Error
+```
+
+### `implicit-inexact-object` {#toc-implicit-inexact-object}
+Like [`ambiguous-object-type`](#toc-ambiguous-object-type), except triggers even when the `exact_by_default` option is set to `false`.
+
+### `nonstrict-import` {#toc-nonstrict-import}
+Used in conjuction with [Flow Strict](../../strict/). Triggers when importing a non `@flow strict` module. When enabled, dependencies of a `@flow strict` module must also be `@flow strict`.
+
+### `sketchy-null` {#toc-sketchy-null}
+Triggers when you do an existence check on a value that can be either null/undefined or falsey.
+
+For example:
+```js flow-check
+// flowlint sketchy-null:error
+
+const x: ?number = 5;
+if (x) {} // sketchy because x could be either null or 0.
+
+const y: number = 5;
+if (y) {} // not sketchy because y can't be null, only 0.
+
+const z: ?{foo: number} = {foo: 5};
+if (z) {} // not sketchy, because z can't be falsey, only null/undefined.
+```
+
+Setting `sketchy-null` sets the level for all sketchy null checks, but there are more granular rules for particular types. These are:
+* `sketchy-null-bool`
+* `sketchy-null-number`
+* `sketchy-null-string`
+* `sketchy-null-mixed`
+* `sketchy-null-bigint`
+
+The type-specific variants are useful for specifying that some types of sketchy null checks are acceptable while others should be errors/warnings. For example, if you want to allow boolean sketchy null checks (for the pattern of treating undefined optional booleans as false) but forbid other types of sketchy null checks, you can do so with this `.flowconfig` `[lints]` section:
+```
+[lints]
+sketchy-null=warn
+sketchy-null-bool=off
+```
+and now
+```js
+function foo (bar: ?bool): void {
+ if (bar) {
+ ...
+ } else {
+ ...
+ }
+}
+```
+doesn't report a warning.
+
+Suppressing one type of sketchy null check only suppresses that type, so, for example
+```js flow-check
+// flowlint sketchy-null:error, sketchy-null-bool:off
+const x: ?(number | bool) = 0;
+if (x) {}
+```
+would still have a `sketchy-null-number` error on line 3.
+
+### `sketchy-number` {#toc-sketchy-number}
+Triggers when a `number` is used in a manner which may lead to unexpected results if the value is falsy.
+Currently, this lint triggers if a `number` appears in:
+* the left-hand side of an `&&` expression.
+
+As a motivating example, consider this common idiom in React:
+
+```js
+{showFoo && }
+```
+
+Here, `showFoo` is a boolean which controls whether or not to display the ` ` element. If `showFoo` is true, then this evaluates to `{ }`. If `showFoo` is false, then this evaluates to `{false}`, which doesn't display anything.
+
+Now suppose that instead of a boolean, we have a numerical value representing, say, the number of comments on a post. We want to display a count of the comments, unless there are no comments. We might naively try to do something similar to the boolean case:
+
+```js
+{count && <>[{count} comments]>}
+```
+
+If `count` is, say, `5`, then this displays "[5 comments]". However, if `count` is `0`, then this displays "0" instead of displaying nothing. (This problem is unique to `number` because `0` and `NaN` are the only falsy values which React renders with a visible result.) This could be subtly dangerous: if this immediately follows another numerical value, it might appear to the user that we have multiplied that value by 10! Instead, we should do a proper conditional check:
+
+```js
+{count ? <>[{count} comments]> : null}
+```
+
+### `unclear-type` {#toc-unclear-type}
+Triggers when you use `any`, `Object`, or `Function` as type annotations. These
+types are unsafe.
+
+```js flow-check
+// flowlint unclear-type:error
+
+declare const a: any; // Error
+declare const c: Object; // Error
+declare const d: Function; // Error
+```
+
+### `unnecessary-invariant` {#toc-unnecessary-invariant}
+Triggers when you use `invariant` to check a condition which we know must be truthy based on the available type information. This is quite conservative: for example, if all we know about the condition is that it is a `boolean`, then the lint will not fire even if the condition must be `true` at runtime.
+
+Note that this lint does not trigger when we know a condition is always `false`. It is a common idiom to use `invariant()` or `invariant(false, ...)` to throw in code that should be unreachable.
+
+```js flow-check
+// flowlint unnecessary-invariant:error
+declare function invariant(boolean): void;
+
+declare const x: Array; // Array is truthy
+invariant(x);
+```
+
+### `unnecessary-optional-chain` {#toc-unnecessary-optional-chain}
+
+Triggers when you use `?.` where it isn't needed. This comes in two main flavors. The first is when the left-hand-side cannot be nullish:
+
+```js flow-check
+// flowlint unnecessary-optional-chain:error
+type Foo = {
+ bar: number
+}
+
+declare const foo: Foo;
+foo?.bar; // Error
+```
+
+The second is when the left-hand-side could be nullish, but the short-circuiting behavior of `?.` is sufficient to handle it anyway:
+
+```js flow-check
+// flowlint unnecessary-optional-chain:error
+type Foo = {
+ bar: {
+ baz: number
+ }
+}
+
+declare const foo: ?Foo;
+foo?.bar?.baz; // Error
+```
+
+In the second example, the first use of `?.` is valid, since `foo` is potentially nullish, but the second use of `?.` is unnecessary. The left-hand-side of the second `?.` (`foo?.bar`) can only be nullish as a result of `foo` being nullish, and when `foo` is nullish, short-circuiting lets us avoid the second `?.` altogether!
+
+```js
+foo?.bar.baz;
+```
+
+This makes it clear to the reader that `bar` is not a potentially nullish property.
+
+### `unsafe-getters-setters` {#toc-unsafe-getters-setters}
+Triggers when you use getters or setters. Getters and setters can have side
+effects and are unsafe.
+
+For example:
+
+```js flow-check
+// flowlint unsafe-getters-setters:error
+let a = 1;
+const o = {
+ get a() { return a; }, // Error: unsafe-getters-setters
+ set b(x: number) { a = x; }, // Error: unsafe-getters-setters
+ c: 10,
+};
+```
+
+### `untyped-import` {#toc-untyped-import}
+Triggers when you import from an untyped file. Importing from an untyped file
+results in those imports being typed as `any`, which is unsafe.
+
+### `untyped-type-import` {#toc-untyped-type-import}
+Triggers when you import a type from an untyped file. Importing a type from an
+untyped file results in an `any` alias, which is typically not the intended behavior.
+Enabling this lint brings extra attention to this case and can help improve Flow
+coverage of typed files by limiting the spread of implicit `any` types.
+
+### `unused-promise` {#toc-unused-promise}
+Triggers when a `Promise` is unused. This can be dangerous, because errors are potentially unhandled, and the code may not execute in the desired order.
+
+A promise can be "used" by...
+* `await`ing it
+* Calling `.then` with a rejection handler (i.e., with two arguments)
+* Calling `.catch`
+* Calling `.finally`
+* Storing it in a variable, passing it to a function, etc.
+
+For example:
+
+```js flow-check
+// flowlint unused-promise:error
+declare function foo(): Promise;
+
+async function bar() {
+ await foo(); // ok
+ foo(); // error, we forgot to await!
+}
+
+function baz() {
+ foo().catch(err => {console.log(err)}); // ok
+ foo(); // error
+}
+```
+
+You can explicitly ignore the promise with the `void` operator (e.g., `void foo();`).
+
+Note: As of v0.201.0, this rule subsumed the `unused-promise-in-async-scope` and `unused-promise-in-sync-scope` rules.
diff --git a/_src/react/component-syntax.md b/_src/react/component-syntax.md
new file mode 100644
index 00000000000..63dc4869f80
--- /dev/null
+++ b/_src/react/component-syntax.md
@@ -0,0 +1,200 @@
+---
+title: Component Syntax
+slug: /react/component-syntax
+---
+
+[Components](https://react.dev/learn/your-first-component) are the foundation for building UIs in React. While components are typically expressed using JavaScript functions, Component Syntax provides component primitive values that provide several advantages over function components, like:
+
+1. More elegant syntax with significantly less verbosity and boilerplate than functions
+2. Type system support tailored specifically for writing React
+3. Better support for [React refs](https://react.dev/learn/manipulating-the-dom-with-refs)
+
+## Basic Usage
+You can declare a component with Component Syntax similar to how you'd declare a function:
+
+```js flow-check
+import * as React from 'react';
+
+component Introduction(name: string, age: number) {
+ return My name is {name} and I am {age} years old
+}
+```
+
+You can use a component directly in JSX: ` `.
+
+There are a few important details to notice here:
+
+1. the prop parameter names declared in the Introduction component are the same as the prop names passed to Introduction in JSX
+2. the order of the parameters in the declaration does not need to match the order that they are provided in JSX
+
+## Parameters
+
+### String Parameters/Renaming Parameters
+
+Components also allow you to rename parameters, which is useful when your parameter name is not a valid JavaScript identifier:
+
+```js flow-check
+import * as React from 'react';
+
+component RenamedParameter(
+ 'required-renamed' as foo: number,
+ 'optional-renamed' as bar?: number,
+ 'optional-with-default-renamed' as baz?: number = 3,
+) {
+ (foo: number); // OK
+ (bar: number | void); // OK
+ (baz: number); // OK
+
+ return ;
+}
+```
+
+### Rest Parameters
+
+Sometimes you do not want to list out every prop explicitly because you do not intend to reference them individually in your component. This is common when you are writing a component that wraps another and need to pass props from your component to the inner one:
+
+```jsx
+import * as React from 'react';
+
+import type {Props as StarProps} from './Star';
+import Star from './Star';
+
+component BlueStar(...props: StarProps) {
+ return ;
+}
+```
+
+Rest parameters use an object type as an annotation, which means you can use existing type utilities like object spreads and Pick to annotate more complex prop patterns:
+
+```js flow-check
+import * as React from 'react';
+
+component OtherComponent(foo: string, bar: number) {
+ return foo + bar;
+}
+
+component FancyProps(
+ ...props: {
+ ...React.PropsOf,
+ additionalProp: string,
+ }
+) {
+ return ;
+}
+```
+
+### Optional Parameters and Defaults
+
+Components allow you to declare optional parameters and specify defaults:
+
+```js flow-check
+import * as React from 'react';
+
+component OptionalAndDefaults(
+ color: string = "blue",
+ extraMessage?: string,
+) {
+ let message = `My favorite color is ${color}.`;
+ if (extraMessage != null) {
+ message += `\n${extraMessage}`;
+ }
+ return {message}
+}
+
+ // No error, all of the parameters are optional!
+```
+
+### Destructuring Parameters
+
+The `as` operator also allows you to destructure your parameters:
+
+```js flow-check
+import * as React from 'react';
+
+component Destructuring(
+ config as {color, height}: $ReadOnly<{color: number, height: number}>,
+) { return }
+```
+
+Rest parameters can be destructured without using as:
+
+```js flow-check
+import * as React from 'react';
+
+type Props = $ReadOnly<{ color: string, height: number }>;
+
+component DestructuredRest(...{color, height}: Props) { return }
+```
+
+### Ref Parameters
+
+To access refs in components you just need to add a ref parameter.
+
+```js flow-check
+import * as React from 'react';
+
+component ComponentWithARef(ref: React.RefSetter) {
+ return ;
+}
+```
+
+Behind the scenes Component Syntax will wrap the component in the required [React.forwardRef call](https://react.dev/reference/react/forwardRef) to ensure the component works as expected at runtime. The one restriction for refs is they must be defined as an inline parameter, refs within rest params are not supported. This is due to the need to compile in the `forwardRef` call, for this to work correctly we need to be able to statically determine the ref from the component definition.
+
+## Elements of Components
+
+For components declared in Component Syntax, you can use `ComponentName` to reference the type of an element of that component.
+For components not using Component Syntax you have to write `React.Element`.
+
+```js flow-check
+import * as React from 'react';
+
+declare component Foo();
+declare component Bar();
+
+const foo: Foo = ;
+const bar: Bar = ; // ERROR
+```
+
+The syntax also works for generic components:
+
+```js flow-check
+import * as React from 'react';
+
+declare component Foo(prop: T);
+
+const foo1: Foo = ;
+const foo2: Foo = ; // Invalid generic type argument
+const foo3: Foo = ; // Missing generic type argument
+```
+
+We do not recommend requiring very specific type of elements. It will make your parent and children components more coupled. Instead, this feature is designed to make expressing [render types](../render-types) easier.
+
+## Rules for Components
+
+Component Syntax enforces a few restrictions in components to help ensure correctness:
+
+1. The return values must be a subtype of `React.Node`, otherwise React may crash while rendering your component.
+2. All branches of a component must end in an explicit return. Even though `undefined` is a valid return value, we've seen many instances where an explicit return would have prevented bugs in production.
+3. You cannot use `this` in a component.
+
+So these components are invalid:
+
+```js flow-check
+import * as React from 'react';
+
+component InvalidReturnValue() {
+ return new Object(); // ERROR: Value does not match `React.Node` type
+}
+
+component ImplicitReturn(someCond: boolean) {
+ if (someCond) {
+ return Hello World!
;
+ }
+ // ERROR: No return in this branch
+}
+
+component UsesThis() {
+ this.foo = 3; // ERROR: Accessing `this`
+ return null;
+}
+```
diff --git a/_src/react/events.md b/_src/react/events.md
new file mode 100644
index 00000000000..7b8bdb0048f
--- /dev/null
+++ b/_src/react/events.md
@@ -0,0 +1,68 @@
+---
+title: Event Handling
+slug: /react/events
+---
+
+The [React docs for handling events](https://react.dev/learn/responding-to-events) show how an event handler can be attached to
+a React element. To type these event handlers you may use the `SyntheticEvent`
+types like this:
+
+```js flow-check
+import {useState} from 'react';
+import * as React from 'react';
+
+function MyComponent(): React.Node {
+ const [state, setState] = useState({count: 0});
+
+ const handleClick = (event: SyntheticEvent) => {
+ // To access your button instance use `event.currentTarget`.
+ event.currentTarget as HTMLButtonElement;
+
+ setState(prevState => ({
+ count: prevState.count + 1,
+ }));
+ };
+
+ return (
+
+ Count: {state.count}
+
+
+ );
+}
+```
+
+There are also more specific synthetic event types like
+`SyntheticKeyboardEvent`, `SyntheticMouseEvent`, or
+`SyntheticTouchEvent`. The `SyntheticEvent` types all take a single type
+argument: the type of the HTML element the event handler was placed on.
+
+If you don't want to add the type of your element instance you can also use
+`SyntheticEvent` with *no* type arguments like so: `SyntheticEvent<>`.
+
+> **Note:** To get the element instance, like `HTMLButtonElement` in the example
+> above, it is a common mistake to use `event.target` instead of
+> `event.currentTarget`. The reason you want to use `event.currentTarget` is
+> that `event.target` may be the wrong element due to [event propagation][].
+
+[event propagation]: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples#example_5_event_propagation
+
+> **Note:** React uses its own event system so it is important to use the
+> `SyntheticEvent` types instead of the DOM types such as `Event`,
+> `KeyboardEvent`, and `MouseEvent`.
+
+The `SyntheticEvent` types that React provides and the DOM events they are
+related to are:
+
+- `SyntheticEvent` for [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event)
+- `SyntheticAnimationEvent` for [AnimationEvent](https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent)
+- `SyntheticCompositionEvent` for [CompositionEvent](https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent)
+- `SyntheticInputEvent` for [InputEvent](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent)
+- `SyntheticUIEvent` for [UIEvent](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent)
+- `SyntheticFocusEvent` for [FocusEvent](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent)
+- `SyntheticKeyboardEvent` for [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)
+- `SyntheticMouseEvent` for [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
+- `SyntheticDragEvent` for [DragEvent](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent)
+- `SyntheticWheelEvent` for [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent)
+- `SyntheticTouchEvent` for [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent)
+- `SyntheticTransitionEvent` for [TransitionEvent](https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent)
diff --git a/_src/react/function-and-class-components.md b/_src/react/function-and-class-components.md
new file mode 100644
index 00000000000..13392b802ad
--- /dev/null
+++ b/_src/react/function-and-class-components.md
@@ -0,0 +1,185 @@
+---
+title: Function/Class Components
+slug: /react/function-and-class-components
+---
+
+Adding Flow types to your [React components](https://react.dev/learn/your-first-component) is incredibly powerful. After typing
+your component, Flow will statically ensure that you are using the component in
+the way it was designed to be used.
+
+## Functional Components {#toc-functional-components}
+
+Adding Flow types to a functional component is the same as [adding types to a standard function](../../types/functions/).
+Just create an object type for the props and Flow will ensure that the props passed to the component match up with what is expected.
+
+```js flow-check
+import React from 'react';
+
+type Props = {
+ foo: number,
+ bar?: string,
+};
+
+function MyComponent(props: Props) {
+ props.doesNotExist; // Error! You did not define a `doesNotExist` prop.
+
+ return {props.bar};
+}
+
+
+```
+
+
+### Adding Default Props to Functional Components {#toc-adding-default-props-to-functional-components}
+
+A nice pattern to add default props to functional components is to use
+[destructuring with default values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment/#default_value).
+By destructuring the props in the function parameter, you can assign a value to any props that are not passed
+to the component (or passed with the value `undefined`).
+
+```js flow-check
+import React from 'react';
+
+type Props = {
+ foo?: number, // foo is optional to pass in.
+ bar: string, // bar is required.
+};
+
+function MyComponent({foo = 42, bar}: Props) {
+ // Flow knows that foo is not null or undefined
+ const baz = foo + 1;
+}
+
+// And we don't need to include foo.
+ ;
+```
+
+## Class Components {#toc-class-components}
+
+To Flowify a [class component](https://react.dev/reference/react/Component#defining-a-class-component), the type of the props can be passed as the first
+argument to the `React.Component` type. This will have the same effect as adding types
+to the `props` parameter of a function component.
+
+```js flow-check
+import React from 'react';
+
+type Props = {
+ foo: number,
+ bar?: string,
+};
+
+class MyComponent extends React.Component {
+ render(): React.Node {
+ this.props.doesNotExist; // Error! You did not define a `doesNotExist` prop.
+
+ return {this.props.bar};
+ }
+}
+
+ ;
+```
+
+Now wherever we use `this.props` in our React component Flow will treat it as
+the `Props` type we defined.
+
+> **Note:** If you don't need to use the `Props` type again you could also
+> define it inline: `extends React.Component<{ foo: number, bar?: string }>`.
+
+`React.Component` is a [generic type](../../types/generics) that takes two type
+arguments: props and state. The second type argument, `State`, is optional. By
+default it is `undefined` so you can see in the example above we did not include
+`State`. We will learn more about state in the next section...
+
+### Adding State {#toc-adding-state}
+
+To add a type for state to your React class component: create a new object
+type, in the example below we name it `State`, and pass it as the second type
+argument to `React.Component`.
+
+```js flow-check
+import React from 'react';
+
+type Props = { /* ... */ };
+
+type State = {
+ count: number,
+};
+
+class MyComponent extends React.Component {
+ state: State = {
+ count: 0,
+ };
+
+ componentDidMount() {
+ setInterval(() => {
+ this.setState(prevState => ({
+ count: prevState.count + 1,
+ }));
+ }, 1000);
+ }
+
+ render(): React.Node {
+ return Count: {this.state.count};
+ }
+}
+
+ ;
+```
+
+In the example above we are using a [React `setState()` updater function](https://react.dev/reference/react/Component#setstate)
+but you could also pass a partial state object to `setState()`.
+
+> **Note:** If you don't need to use the `State` type again you could also
+> define it inline: `extends React.Component<{}, { count: number }>`.
+
+### Using Default Props for Class Components {#toc-using-default-props-for-class-components}
+
+React supports the notion of `defaultProps` which you can think of as default
+function arguments. When you create an element and do not include a prop
+which has a default then React will substitute that prop with its corresponding
+value from `defaultProps`. Flow supports this notion as well. To type default
+props add a `static defaultProps` property to your class.
+
+```js flow-check
+import React from 'react';
+
+type Props = {
+ foo: number, // foo is required.
+ bar: string, // bar is required.
+};
+
+class MyComponent extends React.Component {
+ static defaultProps: {foo: number} = {
+ foo: 42, // ...but we have a default prop for foo.
+ };
+}
+
+// So we don't need to include foo.
+
+```
+
+> **Note:** You don't need to make `foo` nullable in your `Props` type. Flow
+> will make sure that `foo` is optional if you have a default prop for `foo`.
+
+If you add a type annotation to `defaultProps` you can define the type as
+```js flow-check
+type DefaultProps = {
+ foo: number,
+};
+```
+and spread that into the `Props` type:
+```js
+type Props = {
+ ...DefaultProps,
+ bar: string,
+};
+```
+This way you avoid duplicating the properties that happen to have a default value.
+
+> **Note:** You can also apply this format of default props to functional components
+> by adding a `defaultProps` property to a the component function. However, it is generally
+> simpler to use the destructuring pattern described above.
+> ```js flow-check
+> function MyComponent(props: {foo: number}) {}
+> MyComponent.defaultProps = {foo: 42};
+> ```
diff --git a/_src/react/hoc.md b/_src/react/hoc.md
new file mode 100644
index 00000000000..727036ed159
--- /dev/null
+++ b/_src/react/hoc.md
@@ -0,0 +1,179 @@
+---
+title: Higher-order Components
+slug: /react/hoc
+---
+
+A popular pattern in React is the [higher-order component pattern][], so it's
+important that we can provide effective types for higher-order components in
+Flow. If you don't already know what a higher-order component is then make sure
+to read the [React documentation on higher-order components][] before
+continuing.
+
+[higher-order component pattern]: https://facebook.github.io/react/docs/higher-order-components.html
+[React documentation on higher-order components]: https://facebook.github.io/react/docs/higher-order-components.html
+
+You can make use of the [`React.AbstractComponent`](../types/#toc-react-abstractcomponent) type to annotate your higher order components.
+
+### The Trivial HOC {#toc-the-trivial-hoc}
+
+Let's start with the simplest HOC:
+
+```js flow-check
+import * as React from 'react';
+
+function trivialHOC(
+ Component: React.AbstractComponent
+): React.AbstractComponent {
+ return Component;
+}
+```
+
+This is a basic template for what your HOCs might look like. At runtime, this HOC doesn't
+do anything at all. Let's take a look at some more complex examples.
+
+### Injecting Props {#toc-injecting-props}
+
+A common use case for higher-order components is to inject a prop.
+The HOC automatically sets a prop and returns a component which no longer requires
+that prop. For example, consider a navigation prop. How would one type this?
+
+To remove a prop from the config, we can take a component that includes the
+prop and return a component that does not. It's best to construct these
+types using object type spread.
+
+```js flow-check
+import * as React from 'react';
+
+type InjectedProps = {foo: number}
+
+function injectProp(
+ Component: React.AbstractComponent<{...Config, ...InjectedProps}>
+): React.AbstractComponent {
+ return function WrapperComponent(
+ props: Config,
+ ) {
+ return ;
+ };
+}
+
+function MyComponent(props: {
+ a: number,
+ b: number,
+ ...InjectedProps,
+}): React.Node {}
+
+const MyEnhancedComponent = injectProp(MyComponent);
+
+// We don't need to pass in `foo` even though `MyComponent` requires it:
+ ; // OK
+
+// We still require `a` and `b`:
+ ; // ERROR
+```
+
+### Preserving the Instance Type of a Component {#toc-preserving-the-instance-type-of-a-component}
+
+Recall that the instance type of a function component is `void`. Our example
+above wraps a component in a function, so the returned component has the instance
+type `void`.
+
+```js flow-check
+import * as React from 'react';
+
+type InjectedProps = {foo: number}
+
+function injectProp(
+ Component: React.AbstractComponent<{...Config, ...InjectedProps}>
+): React.AbstractComponent {
+ return function WrapperComponent(
+ props: Config,
+ ) {
+ return ;
+ };
+}
+
+// A class component in this example
+class MyComponent extends React.Component<{
+ a: number,
+ b: number,
+ ...InjectedProps,
+}> {}
+
+const MyEnhancedComponent = injectProp(MyComponent);
+
+// If we create a ref object for the component, it will never be assigned
+// an instance of MyComponent!
+const ref = React.createRef();
+
+// Error, mixed is incompatible with MyComponent.
+ ;
+```
+
+We get this error message because `React.AbstractComponent` doesn't set the `Instance` type
+parameter, so it is automatically set to `mixed`. If we wanted to preserve the instance type
+of the component, we can use [`React.forwardRef`](https://reactjs.org/docs/forwarding-refs.html):
+
+```js flow-check
+import * as React from 'react';
+
+type InjectedProps = {foo: number}
+
+function injectAndPreserveInstance(
+ Component: React.AbstractComponent<{...Config, ...InjectedProps}, Instance>
+): React.AbstractComponent {
+ return React.forwardRef((props, ref) =>
+
+ );
+}
+
+class MyComponent extends React.Component<{
+ a: number,
+ b: number,
+ ...InjectedProps,
+}> {}
+
+const MyEnhancedComponent = injectAndPreserveInstance(MyComponent);
+
+const ref = React.createRef();
+
+// All good! The ref is forwarded.
+ ;
+```
+
+### Exporting Wrapped Components {#toc-exporting-wrapped-components}
+
+If you try to export a wrapped component, chances are that you'll run into a missing annotation error:
+
+```js flow-check
+import * as React from 'react';
+
+function trivialHOC(
+ Component: React.AbstractComponent,
+): React.AbstractComponent {
+ return Component;
+}
+
+type Props = $ReadOnly<{bar: number, foo?: number}>;
+
+function MyComponent({bar, foo = 3}: Props): React.Node {}
+
+export const MyEnhancedComponent = trivialHOC(MyComponent); // ERROR
+```
+
+You can add an annotation to your exported component using `React.AbstractComponent`:
+
+```js flow-check
+import * as React from 'react';
+
+function trivialHOC(
+ Component: React.AbstractComponent,
+): React.AbstractComponent {
+ return Component;
+}
+
+type Props = $ReadOnly<{bar: number, foo?: number}>;
+
+function MyComponent({bar, foo = 3}: Props): React.Node {}
+
+export const MyEnhancedComponent: React.AbstractComponent = trivialHOC(MyComponent); // OK
+```
diff --git a/_src/react/index.md b/_src/react/index.md
new file mode 100644
index 00000000000..bfc8c61860e
--- /dev/null
+++ b/_src/react/index.md
@@ -0,0 +1,38 @@
+---
+title: Getting Started
+slug: /react
+description: Learn how to use Flow to effectively type common and advanced React patterns.
+---
+
+Developers will often use Flow and React together, so it is important that Flow
+can effectively type both common and advanced React patterns. This guide will
+teach you how to use Flow to create safer React applications.
+
+In this guide we will assume you know [the React basics](https://react.dev/learn) and focus on adding
+types for patterns you are already familiar with. We will be using examples
+based on `react-dom`, but all of these patterns work in other environments
+like `react-native` as well.
+
+## Setup Flow with React {#toc-setup-flow-with-react}
+
+Flow and Babel work well together, so it doesn't take much to adopt Flow as a
+React user who already uses Babel. If you need to setup Babel with Flow, you can
+follow [this guide](../tools/babel/).
+
+## Check Out Component Syntax
+Flow supports a dedicated syntax for writing React components that we recommend instead of using regular
+function/class components. Ensure you are set up using our [most up-to-date instructions to
+configure your toolchain](../install) and then take a look at the [Component Syntax](./component-syntax) docs.
+
+## React Runtimes
+
+Flow supports the `@babel/plugin-transform-react-jsx` runtime options required
+to use JSX without explicitly importing the React namespace.
+
+If you are using the new automatic runtime, use this configuration in your `.flowconfig` so
+that Flow knows to auto-import `jsx`:
+
+```ini
+[options]
+react.runtime=automatic
+```
diff --git a/_src/react/multiplatform.md b/_src/react/multiplatform.md
new file mode 100644
index 00000000000..ec8c658e118
--- /dev/null
+++ b/_src/react/multiplatform.md
@@ -0,0 +1,132 @@
+---
+title: Multi-platform Support for React Native
+slug: /react/multiplatform
+description: "Flow's support for multiple platforms inside a single React Native codebase"
+---
+
+:::caution
+The feature is still experimental. Behaviors might change in the future.
+:::
+
+## Benefits {#toc-benefits}
+
+React Native supports conditional bundling of files with [platform specific extensions](https://reactnative.dev/docs/platform-specific-code#platform-specific-extensions). For example, if you have different implementations of an Image component for iOS and Android, you can have an `Image.ios.js` file and `Image.android.js` file, and an import of Image can be resolved to either file based on the platform you are targeting.
+
+These platform specific files live under the same repository, but it would normally require two flowconfigs to check them like the following setup:
+
+```toml title=.flowconfig
+; for ios
+[ignore]
+.*\.android\.js$
+[options]
+module.file_ext=.js
+module.file_ext=.ios.js
+```
+
+```toml title=.flowconfig.android
+; for android
+[ignore]
+; Ignore other platform suffixes
+.*\.ios\.js$
+[options]
+module.file_ext=.js
+module.file_ext=.android.js
+```
+
+Flow's optional React Native multi-platform support allows you to check your entire project with mixed platforms under a single Flow root, so that during the development of a module with both .ios and .android files, you no longer have to run both Flow servers and constantly switch between different servers to see type errors on different platforms.
+
+## Quick Start {#toc-quick-start}
+
+You can start by deleting the flowconfig for all other platforms, deleting all the platform specific configs in the only remaining flowconfig, and add the following new lines to the `options` section:
+
+```
+experimental.multi_platform=true
+experimental.multi_platform.extensions=.ios
+experimental.multi_platform.extensions=.android
+```
+
+For example, these are the required changes for the `.flowconfig` example above:
+
+```diff title=.flowconfig
+[ignore]
+- .*\.android\.js$
+[options]
+module.file_ext=.js
+- module.file_ext=.ios.js
++ experimental.multi_platform=true
++ experimental.multi_platform.extensions=.ios
++ experimental.multi_platform.extensions=.android
+```
+
+After enabling the new configurations, there will likely be new errors. The sections below explain the additional rules that Flow imposes to check a multiplatform React Native project.
+
+## Common Interface Files {#toc-common-interface-file}
+
+Suppose you have a file that imports the `Image` module, but `Image` module has different iOS and Android implementations as follows:
+
+```jsx title=MyReactNativeApp.js
+import * as React from 'react';
+import Image from './Image';
+
+ ;
+ ;
+```
+
+```jsx title=Image.ios.js
+import * as React from 'react';
+
+type Props = { src: string, lazyLoading?: boolean };
+
+export default function Image(props: Props): React.Node { /* ... */ }
+```
+
+```jsx title=Image.android.js
+import * as React from 'react';
+
+type Props = { src: string, lazyLoading: boolean };
+
+export default class Image extends React.Components {
+ static defaultProps: { lazyLoading: boolean } = { lazyLoading: false };
+ render(): React.Node { /* ... */ }
+}
+```
+
+When you enabled multiplatform support, you will likely see that error that the `./Image` module cannot be resolved. To fix the error, you need to create a common interface file under the same directory:
+
+### Common Interface File in `.js.flow` {#toc-common-interface-file-in-js-flow}
+
+One option is to write a common interface file in `.js.flow`:
+
+```jsx title=Image.js.flow
+import * as React from 'react';
+
+type Props = { src: string, lazyLoading?: boolean };
+
+declare const Image: React.AbstractComponent;
+export default Image;
+```
+
+Flow will ensure that the module types of both `Image.ios.js` and `./Image.android.js` are subtype of the module type of `./Image.js.flow`. Flow will also ensure that there exists an implementation for each platform you declared in your `.flowconfig`.
+
+### Common Interface File in `.js` {#toc-common-interface-file-in-js}
+
+Sometimes you might target desktop platforms in addition to iOS and Android, and you only have a special implementation for one platform, and all the other platforms will use the fallback implementation in a `.js` file. For example:
+
+```jsx title=Image.js
+import * as React from 'react';
+import DefaultImage from 'react-native/Libraries/Image';
+
+export default DefaultImage;
+```
+
+```jsx title=Image.ios.js
+import * as React from 'react';
+
+type Props = { src: string, lazyLoading: boolean };
+
+export default function Image(props: Props): React.Node {
+ // Custom implementation to take advantage of some unique iOS capabilities
+}
+```
+
+In this case, Flow will use the `.js` file as the common interface file, and check all other platform-specific implementation files' against the `.js` file. Since the `.js` file is already a fallback implementation, Flow will no longer require that platform-specific implementation files exist for all platforms.
diff --git a/_src/react/refs.md b/_src/react/refs.md
new file mode 100644
index 00000000000..900117750b7
--- /dev/null
+++ b/_src/react/refs.md
@@ -0,0 +1,54 @@
+---
+title: Ref Functions
+slug: /react/refs
+---
+
+React allows you to grab the instance of an element or component with [refs](https://react.dev/learn/manipulating-the-dom-with-refs).
+
+## Refs in Functional Components {#toc-refs-in-functional-components}
+
+Inside a functional component, refs are accessed with the `useRef` hook:
+
+```js flow-check
+import {useRef} from 'react';
+import * as React from 'react';
+
+function MyComponent() {
+ const buttonRef = useRef(null);
+ buttonRef as {current: null | HTMLButtonElement}; // useRef wraps the ref value in an object
+ return ;
+}
+```
+
+Note that `useRef` wraps the ref value in an object with a `current` property. This must be
+reflected in the type of anything accepting the ref value.
+
+## Refs in Class Components {#toc-refs-in-class-components}
+
+Refs in class components are similar to function components. To create one, add a
+property to your class and assign the result of `React.createRef` to it.
+
+```js flow-check
+import * as React from 'react';
+
+class MyComponent extends React.Component<{}> {
+ // The `null` here is important because you may not always have the instance.
+ buttonRef: {current: null | HTMLButtonElement};
+
+ constructor() {
+ super();
+ this.buttonRef = React.createRef();
+ }
+
+ render(): React.Node {
+ return ;
+ }
+}
+```
+
+One notable difference between `useRef` and `createRef` is that `createRef` does not accept
+a default value. It will initialize the ref with the value `null`. This is because
+DOM elements will not exist until the first render of `MyComponent` and so a `null` value
+must be used.
+
+Again, note that the ref value is wrapped in an object with a `current` property.
diff --git a/_src/react/render-types.md b/_src/react/render-types.md
new file mode 100644
index 00000000000..092054da7f9
--- /dev/null
+++ b/_src/react/render-types.md
@@ -0,0 +1,301 @@
+---
+title: Render Types
+slug: /react/render-types
+---
+Some component libraries or design systems may want to restrict how components may be composed.
+For example, a Menu should only ever render MenuItems as children. Render types are a built-in way to support
+these constraints while still affording users rich flexibility in how they use those components.
+
+## Basic Behavior
+
+A component can declare what it renders using the renders keyword:
+
+```js flow-check
+import * as React from 'react';
+
+component Header(size: string, color: string) { return }
+
+component LargeHeader(color: string) renders Header {
+ return ; // Ok!
+}
+```
+
+When you declare that your component renders some specific element, you can return any component that eventually renders that component in its renders chain:
+
+```js flow-check
+import * as React from 'react';
+
+component Header(size: string, color: string) { return }
+
+component LargeHeader(color: string) renders Header {
+ return ;
+}
+
+component LargeBlueHeader() renders Header {
+ // You could also use `renders LargeHeader` above
+ return ;
+}
+```
+
+Components can specify props that render specific elements:
+
+```js flow-check
+import * as React from 'react';
+
+component Header(size: string, color: string, message: string) {
+ return {message}
;
+}
+
+component Layout(header: renders Header) {
+ return (
+
+ {header}
+ Hi
+
+ );
+}
+```
+
+And you can pass an element of either Header, or an element of a component that renders `Header`, to that prop:
+
+```js
+ } />;
+```
+
+You cannot pass a component that does not render a header to a render type expecting a header:
+
+```js flow-check
+import * as React from 'react';
+
+component Footer() {
+ return ;
+}
+
+component Header(size: string, color: string, message: string) {
+ return {message}
;
+}
+
+component Layout(header: renders Header) {
+ return {header};
+}
+
+ } />; // ERROR Footer does not render Header
+```
+
+## Integrating with a design system
+
+Render types are designed to make integrating with a design system simple. If a prop in the design system component expects a render type, you can copy/paste that type onto your component to integrate with the design system:
+
+```js flow-check
+import * as React from 'react';
+
+component Header() {
+ return Header!
;
+}
+
+component Layout(header: renders Header) {
+ return {header};
+}
+
+// Copy-paste the header props' type!
+component ProductHeader() renders Header {
+ // We must return a value that renders a Header to satisfy the signature
+ return ;
+}
+
+// And now you can integrate with the design system!
+ } />; // OK!
+```
+
+## Rendering Optional Elements
+
+You may want to describe a component that can take a child that may eventually render an element or nothing. You can use a specialized render type variant `renders?` to achieve this:
+
+```js flow-check
+import * as React from 'react';
+
+component DesignSystemCardFooter() {
+ return Footer Content;
+}
+
+component DesignSystemCard(
+ children: React.Node,
+ footer: renders? DesignSystemCardFooter,
+) {
+ return {children}{footer};
+}
+
+// With these definitions, all of the following work:
+
+ }>Card;
+Card ;
+Card ;
+Card ;
+
+component ProductFooter(hasFooter?: boolean) renders? DesignSystemCardFooter {
+ return hasFooter && ;
+}
+
+ }>Card;
+```
+
+## Rendering Lists
+
+You may want to describe a component that can take any amount of children that render a specific element as props. You can use a specialized render type variant `renders*` to achieve this:
+
+```js flow-check
+import * as React from 'react';
+
+component DesignSystemMenuItem() {
+ return Menu Item ;
+}
+
+component DesignSystemMenu(
+ children: renders* DesignSystemMenuItem,
+) {
+ return {children}
+}
+
+// With these definitions, all of the following work:
+
+const menu1 = (
+
+
+
+);
+
+const menu2 = (
+
+
+
+
+);
+
+const menu3 = (
+
+ {[
+ ,
+ ,
+ ]}
+
+
+);
+
+component ProductMenuItem() renders DesignSystemMenuItem {
+ return ;
+}
+
+const menu4 = (
+
+ {[
+ ,
+ ,
+ ]}
+
+
+);
+```
+
+## Transparent Components
+
+Components can be "transparent":
+
+```js flow-check
+import * as React from 'react';
+
+component TransparentComponent(children: T) renders T {
+ // .. do something
+ return children;
+}
+
+component Header(text: string) {
+ return {text}
;
+}
+component InstagramHeader() renders Header {
+ return ;
+}
+component Layout(
+ header: renders Header,
+) {
+ return {header};
+}
+
+component Page() {
+ const wrappedHeader =
+ return ; // Ok!
+}
+```
+
+## Interop with non-Component-Syntax components
+
+You can use `renders` to annotate function components as well:
+
+```js flow-check
+import * as React from 'react';
+
+component Header(text: string) {
+ return {text}
;
+}
+component InstagramHeader() renders Header {
+ return ;
+}
+component Layout(
+ header: renders Header,
+) {
+ return {header};
+}
+
+function FunctionHeader(): renders Header {
+ return ;
+}
+
+function InstagramPage() {
+ return } />; // OK!
+}
+```
+
+## Subtyping Behavior
+
+All render types are subtypes of `React.Node`, and only `renders Foo` is subtype of `React.MixedElement`.
+
+```js flow-check
+import * as React from 'react';
+
+component Header() {
+ return Hello Header!
;
+}
+
+declare const rendersHeader: renders Header;
+declare const rendersMaybeHeader: renders? Header;
+declare const rendersHeaderList: renders* Header;
+
+rendersHeader as React.Node;
+rendersMaybeHeader as React.Node;
+rendersHeaderList as React.Node;
+
+rendersHeader as React.MixedElement;
+rendersMaybeHeader as React.MixedElement; // ERROR!
+rendersHeaderList as React.MixedElement; // ERROR!
+```
+
+`renders Foo` is a subtype of `renders? Foo`, and `renders? Foo` is a subtype of `renders* Foo`.
+
+```js flow-check
+import * as React from 'react';
+
+component Header() {
+ return Hello Header!
;
+}
+
+declare const rendersHeader: renders Header;
+declare const rendersMaybeHeader: renders? Header;
+declare const rendersHeaderList: renders* Header;
+
+rendersHeader as renders? Header;
+rendersHeader as renders* Header;
+rendersMaybeHeader as renders* Header;
+
+rendersMaybeHeader as renders Header; // ERROR
+rendersHeaderList as renders Header; // ERROR
+rendersHeaderList as renders? Header; // ERROR
+```
diff --git a/_src/react/types.md b/_src/react/types.md
new file mode 100644
index 00000000000..ff1b3ebdab9
--- /dev/null
+++ b/_src/react/types.md
@@ -0,0 +1,332 @@
+---
+title: Type Reference
+slug: /react/types
+---
+
+React exports a handful of utility types that may be useful to you when typing
+advanced React patterns. In previous sections we have seen a few of them. The
+following is a complete reference for each of these types along with some
+examples for how/where to use them.
+
+These types are all exported as named type exports from the `react` module. If
+you want to access them as members on the `React` object (e.g.
+[`React.Node`](#toc-react-node)) and
+you are importing React as an ES module then you should import `React` as a
+namespace:
+
+```js
+import * as React from 'react';
+```
+
+If you are using CommonJS you can also require React:
+
+```js
+const React = require('react');
+```
+
+You can also use named type imports in either an ES module environment or a
+CommonJS environment:
+
+```js
+import type {Node} from 'react';
+```
+
+We will refer to all the types in the following reference as if we imported them
+with:
+
+```js
+import * as React from 'react';
+```
+
+> **Note:** While importing React with a default import works:
+>
+> ```
+> import React from 'react';
+> ```
+>
+> You will have access to all of the values that React exports, but you will
+> **not** have access to the types documented below! This is because Flow will
+> not add types to a default export since the default export could be any value
+> (like a number). Flow will add exported named types to an ES namespace object
+> which you can get with `import * as React from 'react'` since Flow knows if
+> you export a value with the same name as an exported type.
+>
+> Again, if you import React with: `import React from 'react'` you will be able
+> to access `React.Component`, `React.createElement()`, `React.Children`, and
+> other JavaScript *values*. However, you will not be able to access
+> [`React.Node`](#toc-react-node), [`React.ChildrenArray`](#toc-react-childrenarray) or
+> other Flow *types*. You will need to use a named type import like:
+> `import type {Node} from 'react'` in addition to your default import.
+
+## `React.Node` {#toc-react-node}
+
+This represents any node that can be rendered in a React application.
+`React.Node` can be null, a boolean, a number, a string, a React
+element, or an array of any of those types recursively.
+
+`React.Node` is a good default to use to annotate the return type of a function component
+and class render methods. You can also use it to type elements your component takes in as children.
+
+Here is an example of `React.Node` being used as the return type to a function component:
+
+```js
+function MyComponent(props: {}): React.Node {
+ // ...
+}
+```
+
+It may also be used as the return type of a class `render` method:
+```js
+class MyComponent extends React.Component<{}> {
+ render(): React.Node {
+ // ...
+ }
+}
+```
+
+Here is an example of `React.Node` as the prop type for children:
+
+```js
+function MyComponent({ children }: { children: React.Node }) {
+ return {children};
+}
+```
+
+All `react-dom` JSX intrinsics have `React.Node` as their children type.
+``, ``, and all the rest.
+
+## `React.MixedElement` {#toc-react-mixedelement}
+
+The most general type of all React elements (similar to `mixed` for all values). `React.MixedElement` is defined as
+`React.Element`.
+
+A common use case of this type is when we want to annotate an element with a type that hides the element details. For example
+```js
+const element: React.MixedElement = ;
+```
+
+## `React.Element` {#toc-react-element}
+
+A React element is the type for the value of a JSX element:
+
+```js
+const element: React.Element<'div'> = ;
+```
+
+`React.Element` is also the return type of
+`React.createElement()`/`React.jsx()`.
+
+A `React.Element` takes a single type argument,
+`typeof Component`. `typeof Component` is the component type of the React
+element. For an intrinsic element, `typeof Component` will be the string literal
+for the intrinsic you used. Here are a few examples with DOM intrinsics:
+
+```js
+ as React.Element<'div'>; // OK
+ as React.Element<'span'>; // OK
+ as React.Element<'span'>; // Error: div is not a span.
+```
+
+`typeof Component` can also be your React class component or function component.
+
+```js
+function Foo(props: {}) {}
+class Bar extends React.Component<{}> {}
+
+ as React.Element; // OK
+ as React.Element; // OK
+ as React.Element; // Error: Foo is not Bar
+```
+
+Take note of the `typeof`, it is required! We want to get the
+type *of* the value `Foo`. `Foo as Foo` is an error because `Foo` cannot be used
+as a type, so the following is correct: `Foo as typeof Foo`.
+
+`Bar` without `typeof` would be the type of an instance of `Bar`: `new Bar() as Bar`.
+We want the type *of* `Bar` not the type of an instance of `Bar`.
+`Class` would also work here, but we prefer `typeof` for consistency
+with function components.
+
+## `React.ChildrenArray` {#toc-react-childrenarray}
+
+A React children array can be a single value or an array nested to any level.
+It is designed to be used with the [`React.Children` API](https://react.dev/reference/react/Children).
+
+For example if you want to get a normal JavaScript array from a
+`React.ChildrenArray` see the following example:
+
+```js
+import * as React from 'react';
+
+// A children array can be a single value...
+const children: React.ChildrenArray = 42;
+// ...or an arbitrarily nested array.
+const children: React.ChildrenArray = [[1, 2], 3, [4, 5]];
+
+// Using the `React.Children` API can flatten the array.
+const array: Array = React.Children.toArray(children);
+```
+
+## `React.AbstractComponent` {#toc-react-abstractcomponent}
+
+`React.AbstractComponent` represents a component with
+a config of type Config and instance of type Instance.
+
+The `Config` of a component is the type of the object you need to pass in to JSX in order
+to create an element with that component. The `Instance` of a component is the type of the value
+that is written to the `current` field of a ref object passed into the `ref` prop in JSX.
+
+Config is required, but Instance is optional and defaults to mixed.
+
+A class or function component with config `Config` may be used in places that expect
+`React.AbstractComponent`.
+
+This is Flow's most abstract representation of a React component, and is most useful for
+writing HOCs and library definitions.
+
+## `React.ComponentType` {#toc-react-componenttype}
+
+This is the same as [`React.AbstractComponent`](#toc-react-abstractcomponent), but only specifies the first type argument.
+
+## `React.ElementType` {#toc-react-elementtype}
+
+Similar to [`React.AbstractComponent`](#toc-react-abstractcomponent) except it also
+includes JSX intrinsics (strings).
+
+The definition for `React.ElementType` is roughly:
+
+```js
+type ElementType =
+ | string
+ | React.AbstractComponent;
+```
+
+## `React.Key` {#toc-react-key}
+
+The type of the key prop on React elements. It is a union of strings and
+numbers defined as:
+
+```js
+type Key = string | number;
+```
+
+## `React.Ref` {#toc-react-ref}
+
+The type of the [ref prop on React elements][]. `React.Ref`
+could be a string, ref object, or ref function.
+
+[ref prop on React elements]: https://react.dev/learn/manipulating-the-dom-with-refs
+
+The ref function will take one and only argument which will be the element
+instance which is retrieved using
+[`React.ElementRef`](#toc-react-elementref) or null since
+[React will pass null into a ref function when unmounting][].
+
+[React will pass null into a ref function when unmounting]: https://react.dev/learn/manipulating-the-dom-with-refs#how-to-manage-a-list-of-refs-using-a-ref-callback
+
+Like [`React.Element`](#toc-react-element), `typeof Component`
+must be the type *of* a React component so you need to use `typeof` as in
+`React.Ref`.
+
+The definition for `React.Ref` is roughly:
+
+```js
+type Ref =
+ | string
+ | (instance: React.ElementRef | null) => mixed;
+ | { -current: React$ElementRef | null, ... }
+```
+## `React.PropsOf` {#toc-react-propsof}
+When `Component` is written using [Component Syntax](../component-syntax), `React.PropsOf`
+gives you the type of an object that you must pass in to instantiate `Component` with JSX.
+Importantly, the props with defaults are optional in the resulting type.
+
+For example:
+```js flow-check
+import * as React from 'react';
+
+component MyComponent(foo: number, bar: string = 'str') {
+ return null;
+}
+
+// Only foo is required
+({foo: 3}) as React.ElementConfig;
+```
+
+## `React.ElementConfig` {#toc-react-elementconfig}
+
+Like [React.PropsOf](#toc-react-propsof), this utility gets the type of the object that you must pass in to a
+component in order to instantiate it via `createElement()` or `jsx()`. While `PropsOf` takes in an element of
+a component, which is convenient when using [Component Syntax](../component-syntax), `ElementConfig` takes in the type of a component
+instead. `typeof Component` must be the type *of* a React component so you need to use `typeof` as in
+`React.ElementConfig`.
+
+Importantly, props with defaults are optional in the resulting type.
+
+For example,
+
+```js
+import * as React from 'react';
+
+class MyComponent extends React.Component<{foo: number}> {
+ static defaultProps = {foo: 42};
+
+ render() {
+ return this.props.foo;
+ }
+}
+
+// `React.ElementProps<>` requires `foo` even though it has a `defaultProp`.
+({foo: 42}) as React.ElementProps;
+
+// `React.ElementConfig<>` does not require `foo` since it has a `defaultProp`.
+({}) as React.ElementConfig;
+```
+
+Like [`React.Element`](#toc-react-element), `typeof Component` must be the
+type *of* a React component so you need to use `typeof` as in
+`React.ElementProps`.
+
+
+## `React.ElementProps` {#toc-react-elementprops}
+
+> **Note:** Because [`React.ElementProps`](#toc-react-elementprops) does not preserve the optionality of `defaultProps`, [`React.ElementConfig`](#toc-react-elementconfig) (which does) is more often the right choice, especially for simple props pass-through as with [higher-order components](../hoc/#toc-supporting-defaultprops-with-react-elementconfig).
+You probably should not use ElementProps.
+
+Gets the props for a React element type, *without* preserving the optionality of `defaultProps`.
+`typeof Component` could be the type of a React class component, a function component, or a JSX intrinsic string.
+This type is used for the `props` property on [`React.Element`](#toc-react-element).
+
+Like [`React.Element`](#toc-react-element), `typeof Component` must be the
+type *of* a React component so you need to use `typeof` as in
+`React.ElementProps`.
+## `React.RefOf` {#toc-react-refof}
+
+When using [Component Syntax](../component-syntax), `React.RefOf` will give you
+the type of the `current` field on the `ref` prop of the component. If there is no `ref` prop
+on the component it will return `void`.
+
+## `React.ElementRef` {#toc-react-elementref}
+
+Gets the instance type for a React element. The instance will be different for
+various component types:
+
+- React.AbstractComponent will return the Instance type.
+- React class components will be the class instance. So if you had
+ `class Foo extends React.Component<{}> {}` and used
+ `React.ElementRef` then the type would be the instance of `Foo`.
+- React function components do not have a backing instance and so
+ `React.ElementRef` (when `Bar` is `function Bar() {}`) will give
+ you the void type.
+- JSX intrinsics like `div` will give you their DOM instance. For
+ `React.ElementRef<'div'>` that would be `HTMLDivElement`. For
+ `React.ElementRef<'input'>` that would be `HTMLInputElement`.
+
+Like [`React.Element`](#toc-react-element), `typeof Component` must be the
+type *of* a React component so you need to use `typeof` as in
+`React.ElementRef`.
+
+## `React.Config` {#toc-react-config}
+
+Calculates a config object from props and default props. This is most useful for annotating
+HOCs that are abstracted over configs. See our [docs on writing HOCs](../hoc) for more information.
diff --git a/_src/strict/index.md b/_src/strict/index.md
new file mode 100644
index 00000000000..f7eb60295a1
--- /dev/null
+++ b/_src/strict/index.md
@@ -0,0 +1,58 @@
+---
+title: Flow Strict
+slug: /strict
+description: Learn how to enable stricter type checking on a file-by-file basis.
+---
+
+You can enable stronger safety guarantees in Flow (such as banning `any`/`Object`/`Function` types and requiring all dependencies to be typed) by adding **`@flow strict`** to your files.
+
+### Overview {#toc-overview}
+Flow was designed for easy adoption, so it allows you opt-out of type checking in certain situations, permitting unsafe behaviors. But since many codebases now have a high adoption of Flow types, this trade-off can be flipped. You can use *Flow Strict* to disallow previously-allowed unsafe patterns. This gives you improved safety guarantees that catch more bugs and make refactoring easier. And you can implement these stronger guarantees incrementally, on a file-by-file basis.
+
+### Features {#toc-features}
+Enabling Flow Strict for a file means that several previously-allowed patterns will now trigger a Flow error. Each disallowed pattern has a corresponding [Flow Lint](../linting/) rule which triggers the error. The list of rules enabled for `@flow strict` is configured in each `.flowconfig`. Here are the recommended rules:
+
+ - [`nonstrict-import`](../linting/rule-reference/#toc-nonstrict-import): Triggers an error when importing from a module which is not also `@flow strict`. This is very important, because it means that when a file is marked as strict, all of its dependencies are strict as well.
+ - [`unclear-type`](../linting/rule-reference/#toc-unclear-type): Triggers an error when using `Object`, `Function`, or `any` in a type annotation.
+ - [`untyped-import`](../linting/rule-reference/#toc-untyped-import): Triggers an error when importing from an untyped module.
+ - [`untyped-type-import`](../linting/rule-reference/#toc-untyped-type-import): Triggers an error when importing a type from an untyped module.
+ - [`unsafe-getters-setters`](../linting/rule-reference/#toc-unsafe-getters-setters): Triggers an error when using getters and setters, which can be unsafe.
+ - [`sketchy-null`](../linting/rule-reference/#toc-sketchy-null): Triggers an error when doing an existence check on a value that could be null/undefined or falsey.
+
+For a full list of available lint rules, see the [Lint Rule Reference](../linting/rule-reference/).
+
+Additionally, note that function parameters are considered const (i.e., treated as if they were declared with `const` rather than `let`). This feature is not yet configurable in Flow Strict; it is always on.
+
+### Enabling Flow Strict in a .flowconfig {#toc-enabling-flow-strict-in-a-flowconfig}
+Flow Strict is configured in each `.flowconfig`. To enable:
+1. Add a `[strict]` section to the `.flowconfig`.
+2. List the lint rules to enable . These are strongly recommended:
+```text
+[strict]
+nonstrict-import
+unclear-type
+unsafe-getters-setters
+untyped-import
+untyped-type-import
+```
+Also recommended, but optional as it may be too noisy in some codebases:
+`sketchy-null`
+
+We recommend you enable all your desired rules from the beginning, then adopt Flow Strict file-by-file. This works better than enabling a single rule, adding `@flow strict` to many files, and then adding more rules to the config.
+
+### Adoption {#toc-adoption}
+Add `@flow strict` to a file and fix all errors that appear. Because Flow Strict requires dependencies to also be strict (if the `nonstrict-import` rule is enabled), start at the leaves of the dependency tree and work up from there. Do not add `$FlowFixMe` to suppress the new errors as they appear; just add `@flow strict` once all issues have been resolved. Since the most common reasons for using `$FlowFixMe` stem from reliance on untyped dependencies or behavior, future issues should be greatly reduced once Flow Strict is enabled.
+
+Be liberal with enabling Flow Strict. Unlike adding or removing `@flow`, adding or removing `@flow strict` (by itself) does not change Flow coverage. It only prevents or allows certain new unsafe behavior from being added in the future. Even if in the future Flow Strict has to be disabled for the file, at least unsafe behavior was prevented from being added in the meantime.
+
+Library definitions are considered strict (as they can be included in many different projects with contradicting strict configurations).
+
+### Strict Local {#toc-strict-local}
+If you enable the `nonstrict-import` rule in your Flow Strict configuration (recommended), then all dependencies of a strict file must also be strict. While this the optimal goal, for large pre-existing codebases it may be beneficial to allow some of the benefits of Flow Strict to be put in use before all dependencies are strict.
+
+`@flow strict-local` is the same as `@flow strict`, except it does not require its dependencies to also be strict (i.e. it is "locally" strict). It does not have a separate configuration: it uses the same configuration as Flow Strict, just without the `nonstrict-import` rule.
+
+Once all the dependencies of a `@flow strict-local` file are strict, the file can be upgraded to a `@flow strict` file. A `@flow strict` file cannot depend on a `@flow strict-local` file as this would break the `nonstrict-import` rule.
+
+### What's Ahead {#toc-what-s-ahead}
+Eventually, some features of Flow Strict could become the default behavior of Flow, if those features prove successful and achieve widespread adoption.
diff --git a/_src/tools/babel.md b/_src/tools/babel.md
new file mode 100644
index 00000000000..cb7b9a7a8dd
--- /dev/null
+++ b/_src/tools/babel.md
@@ -0,0 +1,30 @@
+---
+title: Babel
+slug: /tools/babel
+---
+
+Flow and [Babel](http://babeljs.io/) are designed to work great together. It
+takes just a few steps to set them up together.
+
+If you don't have Babel setup already, you can do that by following
+[this guide](http://babeljs.io/docs/setup/).
+
+Once you have Babel setup, install `@babel/preset-flow` and `babel-plugin-syntax-hermes-parser` with either
+[Yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/).
+
+```sh
+yarn add --dev @babel/preset-flow babel-plugin-syntax-hermes-parser
+# or
+npm install --save-dev @babel/preset-flow babel-plugin-syntax-hermes-parser
+```
+
+Then add the `@babel/preset-flow` preset and `babel-plugin-syntax-hermes-parser` plugin to your Babel config.
+
+```json
+{
+ "presets": ["@babel/preset-flow"],
+ "plugins": ["babel-plugin-syntax-hermes-parser"],
+}
+```
+
+You can read the documentation of [babel-plugin-syntax-hermes-parser](https://github.com/facebook/hermes/blob/main/tools/hermes-parser/js/babel-plugin-syntax-hermes-parser/README.md) to see how to configure it. [This website's Babel config](https://github.com/facebook/flow/blob/baa74a889dc81fe36f0fd362db6d3e27d44d961d/website/babel.config.js#L10-L17) provides an example with custom parser options.
diff --git a/_src/tools/eslint.md b/_src/tools/eslint.md
new file mode 100644
index 00000000000..21385ba1b01
--- /dev/null
+++ b/_src/tools/eslint.md
@@ -0,0 +1,104 @@
+---
+title: ESLint
+slug: /tools/eslint
+---
+
+ESLint is a static analysis tool which can help you quickly find and
+fix bugs and stylistic errors in your code. The rules ESLint provide
+complement the checks provided by Flow's type system.
+
+You can quick-start setup ESLint, install `hermes-eslint` with either
+[Yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/).
+
+```sh
+yarn add --dev eslint hermes-eslint eslint-plugin-ft-flow
+# or
+npm install --save-dev eslint hermes-eslint eslint-plugin-ft-flow
+```
+
+Then create a `.eslintrc.js` file in your project root with the following:
+
+```js
+module.exports = {
+ root: true,
+ parser: 'hermes-eslint',
+ plugins: [
+ 'ft-flow'
+ ],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:ft-flow/recommended',
+ ],
+};
+```
+
+In the above config the order of the `extends` plugins is important as `plugin:ft-flow/recommended`
+disables some rules from `eslint:recommended` so it needs to be defined after to work correctly.
+
+For more information about configuring ESLint, [check out the ESLint docs](https://eslint.org/).
+
+You can then lint your codebase with:
+
+```sh
+yarn run eslint . --ext .js,.jsx
+# or
+npm run eslint . --ext .js,.jsx
+```
+
+### Usage With Prettier {#toc-usage-with-prettier}
+
+If you use [`prettier`](https://www.npmjs.com/package/prettier), there is also
+a helpful config to help ensure ESLint doesn't report on formatting issues that
+prettier will fix: [`eslint-config-prettier`](https://www.npmjs.com/package/eslint-config-prettier).
+
+Using this config by adding it to the **_end_** of your `extends`:
+
+```diff
+ module.exports = {
+ root: true,
+ parser: 'hermes-eslint',
+ plugins: [
+ 'ft-flow'
+ ],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:ft-flow/recommended',
++ 'prettier',
+ ],
+ };
+```
+
+
+### Additional Plugins {#toc-additional-plugins}
+
+ESLint plugins provide additional rules and other functionality on top of ESLint.
+Below are just a few examples that might be useful:
+
+- Helpful language rules by the Flow team: [`eslint-plugin-fb-flow`](https://www.npmjs.com/package/eslint-plugin-fb-flow)
+- React best practices: [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react)
+ and [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks)
+- Jest testing: [`eslint-plugin-jest`](https://www.npmjs.com/package/eslint-plugin-jest)
+- Import/export conventions : [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import)
+- NodeJS best practices: [`eslint-plugin-node`](https://www.npmjs.com/package/eslint-plugin-node)
+- ESLint comment restrictions: [`eslint-plugin-eslint-comments`](https://www.npmjs.com/package/eslint-plugin-eslint-comments)
+
+Every plugin that is out there includes documentation on the various configurations and rules they offer.
+A typical plugin might be used like:
+
+```diff
+ module.exports = {
+ root: true,
+ parser: 'hermes-eslint',
+ plugins: [
+ 'ft-flow'
++ 'jest',
+ ],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:ft-flow/recommended',
++ 'plugin:jest/recommended',
+ ],
+ };
+```
+
+Search ["eslint-plugin" on npm](https://www.npmjs.com/search?q=eslint-plugin) for more.
diff --git a/_src/tools/flow-remove-types.md b/_src/tools/flow-remove-types.md
new file mode 100644
index 00000000000..628e30b7e47
--- /dev/null
+++ b/_src/tools/flow-remove-types.md
@@ -0,0 +1,41 @@
+---
+title: flow-remove-types
+slug: /tools/flow-remove-types
+---
+
+[`flow-remove-types`](https://github.com/facebook/flow/tree/master/packages/flow-remove-types) is a small
+CLI tool for stripping Flow type annotations from files. It's a lighter-weight
+alternative to Babel for projects that don't need everything Babel provides.
+
+First install `flow-remove-types` with either
+[Yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/).
+
+```sh
+yarn add --dev flow-remove-types
+# or
+npm install --save-dev flow-remove-types
+```
+
+If you then put all your source files in a `src` directory you can compile them
+to another directory by running:
+
+```sh
+yarn run flow-remove-types src/ -d lib/
+```
+
+You can add this to your `package.json` scripts easily.
+
+```json
+{
+ "name": "my-project",
+ "main": "lib/index.js",
+ "scripts": {
+ "build": "flow-remove-types src/ -d lib/",
+ "prepublish": "yarn run build"
+ }
+}
+```
+
+> **Note:** You'll probably want to add a `prepublish` script that runs this
+> transform as well, so that it runs before you publish your code to the npm
+> registry.
diff --git a/_src/tools/index.md b/_src/tools/index.md
new file mode 100644
index 00000000000..a5c280a11c9
--- /dev/null
+++ b/_src/tools/index.md
@@ -0,0 +1,14 @@
+---
+title: Tools
+slug: /tools
+displayed_sidebar: docsSidebar
+description: Detailed guides, tips, and resources on how to integrate Flow with different JavaScript tools.
+---
+
+import DocCardList from '@theme/DocCardList';
+
+
diff --git a/_src/types/aliases.md b/_src/types/aliases.md
new file mode 100644
index 00000000000..403451cc86e
--- /dev/null
+++ b/_src/types/aliases.md
@@ -0,0 +1,89 @@
+---
+title: Type Aliases
+slug: /types/aliases
+---
+
+When you have complicated types that you want to reuse in multiple places, you
+can alias them in Flow using a **type alias**.
+
+```js flow-check
+type MyObject = {
+ foo: number,
+ bar: boolean,
+ baz: string,
+};
+```
+
+These type aliases can be used anywhere a type can be used.
+
+```js flow-check
+type MyObject = {
+ // ...
+};
+
+const val: MyObject = { /* ... */ };
+function method(val: MyObject) { /* ... */ }
+class Foo { constructor(val: MyObject) { /* ... */ } }
+```
+
+Type aliases are just that: aliases. They don't create a _different_ type, just another name for one.
+This means that a type alias is completely interchangeable with the type it is equal to.
+
+```js flow-check
+type MyNumber = number;
+declare const x: MyNumber;
+declare function foo(x: number): void;
+foo(x); // ok, because MyNumber = number
+```
+
+[Opaque type aliases](../opaque-types) offer an alternative for when you don't want to treat the
+types as the same.
+
+## Type Alias Syntax {#toc-type-alias-syntax}
+
+Type aliases are created using the keyword `type` followed by its name, an
+equals sign `=`, and a type definition.
+
+```js
+type Alias = Type;
+```
+
+Any type can appear inside a type alias.
+
+```js flow-check
+type NumberAlias = number;
+type ObjectAlias = {
+ property: string,
+ method(): number,
+};
+type UnionAlias = 1 | 2 | 3;
+type AliasAlias = ObjectAlias;
+```
+
+#### Type Alias Generics {#toc-type-alias-generics}
+
+Type aliases can also have their own [generics](../generics).
+
+```js flow-check
+type MyObject = {
+ property: A,
+ method(val: B): C,
+};
+```
+
+Type alias generics are [parameterized](../generics#toc-parameterized-generics).
+When you use a type alias you need to pass parameters for each of its generics.
+
+```js flow-check
+type MyObject = {
+ foo: A,
+ bar: B,
+ baz: C,
+};
+
+var val: MyObject = {
+ foo: 1,
+ bar: true,
+ baz: 'three',
+};
+```
diff --git a/_src/types/any.md b/_src/types/any.md
new file mode 100644
index 00000000000..02cdd60dd44
--- /dev/null
+++ b/_src/types/any.md
@@ -0,0 +1,93 @@
+---
+title: Any
+slug: /types/any
+---
+
+> **Warning:** Do not mistake `any` with [`mixed`](../mixed). It's also not the same as [`empty`](../empty).
+
+If you want a way to opt-out of using the type checker, `any` is the way to do
+it. **Using `any` is completely unsafe, and should be avoided whenever
+possible.**
+
+For example, the following code will not report any errors:
+
+```js flow-check
+function add(one: any, two: any): number {
+ return one + two;
+}
+
+add(1, 2); // Works.
+add("1", "2"); // Works.
+add({}, []); // Works.
+```
+
+Even code that will cause runtime errors will not be caught by Flow:
+
+```js flow-check
+function getNestedProperty(obj: any) {
+ return obj.foo.bar.baz;
+}
+
+getNestedProperty({});
+```
+
+There are only a couple of scenarios where you might consider using `any`:
+
+1. When you are in the process of converting existing code to using Flow
+ types and you are currently blocked on having the code type checked (maybe
+ other code needs to be converted first).
+2. When you are certain your code works and for some reason Flow is unable to
+ type check it correctly. There are a (decreasing) number of idioms in
+ JavaScript that Flow is unable to statically type.
+
+You can ban `any` by enabling the [`unclear-type`](../../linting/rule-reference/#toc-unclear-type) lint rule.
+
+You can use the [coverage](../../cli/coverage/) command to identify code typed as `any`.
+
+## Avoid leaking `any` {#toc-avoid-leaking-any}
+
+When you have a value with the type `any`, you can cause Flow to infer `any`
+for the results of all of the operations you perform.
+
+For example, if you get a property on an object typed `any`, the resulting
+value will also have the type `any`.
+
+```js flow-check
+function fn(obj: any) {
+ let foo = obj.foo; // Results in `any` type
+}
+```
+
+You could then use the resulting value in another operation, such as adding it
+as if it were a number and the result will also be `any`.
+
+```js flow-check
+function fn(obj: any) {
+ let foo = obj.foo; // Results in `any` type
+ let bar = foo * 2; // Results in `any` type
+}
+```
+
+You could continue this process until `any` has leaked all over your code.
+
+```js flow-check
+function fn(obj: any) {
+ let foo = obj.foo;
+ let bar = foo * 2;
+ return bar; // Results in `any` type
+}
+
+let bar = fn({ foo: 2 }); // Results in `any` type
+let baz = "baz:" + bar; // Results in `any` type
+```
+
+Prevent this from happening by cutting `any` off as soon as possible by casting
+it to another type.
+
+```js flow-check
+function fn(obj: any) {
+ let foo: number = obj.foo;
+}
+```
+
+Now your code will not leak `any`.
diff --git a/_src/types/arrays.md b/_src/types/arrays.md
new file mode 100644
index 00000000000..025b6d80e75
--- /dev/null
+++ b/_src/types/arrays.md
@@ -0,0 +1,266 @@
+---
+title: Arrays
+slug: /types/arrays
+---
+
+Array types represent lists of **unknown length**, where all items have the **same type**.
+This is in contrast to [tuple types](../tuples), which have a fixed length and where each element can have a different type.
+
+JavaScript array literal values can be used to create both tuple and array types:
+
+```js flow-check
+const arr: Array = [1, 2, 3]; // As an array type
+const tup: [number, number, number] = [1, 2, 3]; // As a tuple type
+```
+
+## `Array` Type {#toc-array-type}
+
+The type `Array` represents an array of items of type `T`.
+For example, an array of numbers would be `Array`:
+
+```js flow-check
+const arr: Array = [1, 2, 3];
+```
+
+You can put any type within `Array`:
+
+```js flow-check
+const arr1: Array = [true, false, true];
+const arr2: Array = ["A", "B", "C"];
+const arr3: Array = [1, true, "three"];
+```
+
+## `$ReadOnlyArray` Type {#toc-readonlyarray}
+
+You can use the type `$ReadOnlyArray` instead of `Array` to represent a [read-only](../../lang/variance) array which cannot be mutated.
+You can't write to a read-only array directly, and can't use methods which mutate the array like `.push()`, `.unshift()`, etc.
+
+```js flow-check
+const readonlyArray: $ReadOnlyArray = [1, 2, 3]
+
+const first = readonlyArray[0]; // OK to read
+readonlyArray[1] = 20; // Error!
+readonlyArray.push(4); // Error!
+readonlyArray.unshift(4); // Error!
+```
+
+Note that an array of type `$ReadOnlyArray` can still have mutable _elements_:
+
+```js flow-check
+const readonlyArray: $ReadOnlyArray<{x: number}> = [{x: 1}];
+readonlyArray[0] = {x: 42}; // Error!
+readonlyArray[0].x = 42; // Works
+```
+
+The main advantage to using `$ReadOnlyArray` instead of `Array` is that `$ReadOnlyArray`'s
+type parameter is [*covariant*](../../lang/variance/#toc-covariance)
+while `Array`'s type parameter is [*invariant*](../../lang/variance/#toc-invariance).
+That means that `$ReadOnlyArray` is a subtype of `$ReadOnlyArray` while
+`Array` is NOT a subtype of `Array`. So it's often useful to use
+`$ReadOnlyArray` in type annotations for arrays of various types of elements.
+Take, for instance, the following scenario:
+
+```js flow-check
+const someOperation = (arr: Array) => {
+ // Here we could do `arr.push('a string')`
+}
+
+const array: Array = [1];
+someOperation(array) // Error!
+```
+
+Since the parameter `arr` of the `someOperation` function is typed as a mutable
+`Array`, pushing a string into it would be possible inside that scope, which
+would then break the type contract of the outside `array` variable. By
+annotating the parameter as `$ReadOnlyArray` instead in this case, Flow can be
+sure this won't happen and no errors will occur:
+
+```js flow-check
+const someOperation = (arr: $ReadOnlyArray) => {
+ // Nothing can be added to `arr`
+}
+
+const array: Array = [1];
+someOperation(array); // Works
+```
+
+`$ReadOnlyArray` represents the supertype of all arrays and all [tuples](../tuples):
+
+```js flow-check
+const tup: [number, string] = [1, 'hi'];
+const arr: Array = [1, 2];
+
+function f(xs: $ReadOnlyArray) { /* ... */ }
+
+f(tup); // Works
+f(arr); // Works
+```
+
+## Empty Array Literals {#toc-empty-array-literals}
+
+Empty array literals (`[]`) are handled specially in Flow when it comes to their [annotation requirements](../../lang/annotation-requirement).
+What makes them special is that they do not contain enough information to
+determine their type, and at the same time they are too common to always
+require type annotations in their immediate context.
+
+So, to type empty arrays Flow follows these rules:
+
+### Contextual Inference
+
+First, if [contextual information](../../lang/annotation-requirement/#toc-contextual-typing) exists,
+we'll use it to determine the array element type:
+
+```js flow-check
+function takesStringArray(x: Array): void {}
+
+const arr1: Array = [];
+takesStringArray([]);
+```
+
+In both cases, the `[]` will be typed as an `Array