Notes on Flow 0.100
Tags: flowtype
Published: 2019-06-25 10:32:15


Flow [0.100](https://github.com/facebook/flow/releases/tag/v0.100.0) is out 💯. Reading and learning about Flow and JavaScript as always. This time, I have a short note on object destructuring, React type definitions, and put a link to a nice article explaining variance sigils.


Flow 0.100 has very nice release notes with examples. So I won't repeat what is already said there. Here are some bullet points I jotted down as I tried to learn about the changes.

---

## Destructuring objects in function parameters

> Destructuring patterns could previously include missing properties if the resulting binding was unused. This is now an error even when unused. [Try Flow example](https://flow.org/try/#0C4TwDgpgBA8lC8UDeUwC4oGdgCcCWAdgOZQC+A3AFAD01UAojjgPY4YAqAFhDtHplALNULSDlBQABgEdJUQlFCQpMSQBooAQwHMAZlABiAG2YB3KADcADADoAjFdtXKugK4EAxsDzMCUXQAUSGAa0qQYMACUyKRAA)

```js
type O = { p: string }
// Error: There is no property `q` in type `O`, as of Flow v0.100.0
function f({ p, q }: O) {}
```

One confusion I encountered was this

> Does it mean all object will be exact?

So I took this chance to clarify some of the things around here. Exact means the object passed in here _must not_ contain extra fields ([link to doc](https://flow.org/en/docs/types/objects/#toc-exact-object-types)).

Sealed, on the other hand, means the object may contain other fields but you may not access them unless you annotate them. When we write an object type with some fields, it is by default _sealed_. Trying to access unannotated field of a sealed object will result in error, regardless of it being exact or not:

```js
type Sealed = { foo: string }

const sealed = {
  foo: 'foo',
}
sealed.bar = 'bar' // error
const { foo, bar } = sealed // error
```

For functions that expect sealed objects, you can still pass in objects with extra props.

```js
function usingSealed(x: Sealed) {
  // does things
}
usingSealed({ foo: 'foo', bar: 'bar' }) // ok
```

Not so when the functions are expecting _exact_ objects:

```js
type Exact = {| foo: string |}

function usingExact(x: Exact) {
  // does things
}
usingExact({ foo: 'foo', bar: 'bar' }) // error
```

We may access the fields of function parameters by destructuring the object:

<!-- prettier-ignore-start -->
```js
// destructuring on function parameter
function goodUsingSealed({ foo }: Sealed) { // ok
  // does things
}
```
<!-- prettier-ignore-end -->

But since destructuring means accessing the object, we _should not_ be able to access extra props to sealed objects. This is fixed in 0.100:

<!-- prettier-ignore-start -->
```js
// fixed in 0.100
function badUsingSealed({ foo, bar }: Sealed) { // error after 0.100
  // does things
}
```
<!-- prettier-ignore-end -->

---

## React component types

There are a bunch of changes around React library definitions. And so it's a good chance to take a step back and look at what they are in all.

[Here](https://github.com/facebook/flow/blob/master/lib/react.js) is the link to the React library definitions by Flow.

My list of commonly used:

- `React$Component<Props, State = void>`
- `AbstractComponent<-Config, +Instance = mixed>`
- `React$ComponentType<-Config>`
- `React$ElementType`
- `React$Element<+ElementType: React$ElementType>`
- (new) `React$MixedElement = React$Element<React$ElementType>`
- (new) `MixedElement = React$MixedElement`
- `React$Ref<ElementType: React$ElementType>`

In the definitions above, those with the angled brackets are polymorphic types. This means you'll need to supply type parameters for those polymorphics.

### `React$Component<Props, State = void>`

`React$Component` is the base class of ES6 React classes, modeled as a polymorphic class whose main type parameters are Props and State.

### `React$AbstractComponent`

`React$AbstractComponent` is the type name used by Flow, and is used by a few different types of React classes and components in React's library declarations.

`React.AbstractComponent` uses it directly, which takes two parameters, `Config` for the props type, and `Instance` for an instance. Functional components have `Instance: void`.

### `React$ComponentType`

```jsx
declare type React$ComponentType<-Config> = React$AbstractComponent<
  Config,
  mixed
>
```

Aliased to `React$AbstractComponent<Config, mixed>`, and is used as the type of a component in React. It can be:

- Stateless functional components. Functions that take in props as an argument and return a React node.
- ES6 class component. Components with state defined either using the ES6 class syntax, or with the legacy `React.createClass()` helper.

### `React$ElementType`

```jsx
declare type React$ElementType = string | React$AbstractComponent<empty, mixed>
```

The type of an element in React. A React element may be a:

- `string`: These elements are intrinsics that depend on the React renderer implementation.
- React component. See `ComponentType` for more information about its different variants.

A few more related with `ElementType`:

A `React$Element` is the type of a React element. React elements are commonly created using JSX literals, which desugar to React.createElement calls (see below).

```jsx
declare type React$Element<+ElementType: React$ElementType> = {|
  +type: ElementType,
  +props: React$ElementProps<ElementType>,
  +key: React$Key | null,
  +ref: any,
|}
```

Finally, here are the two new types:

```jsx
declare type React$MixedElement = React$Element<React$ElementType>
declare type MixedElement = React$MixedElement
```

A keen reader may have noticed that above is more or less a copy and paste of comments and code snippets from Flow's codebase. They are really very well-written and a significant portion of the code itself is self-explanatory.

---

## Variance sigils

Variance sigils are everywhere in library definitions. If this set of synonyms works for you, feel free to think of covariance as read-only, and contravariance as write-only.

This article [Flow's Best Kept Secret](https://medium.com/@forbeslindesay/covariance-and-contravariance-c3b43d805611) explains it very well.

## 🐶 Till next time

[Flow 0.101](https://github.com/facebook/flow/releases/tag/v0.101.0) is already out and I'm falling behind 😭 It's [JSConf.Asia](https://2019.jsconf.asia/) at home now. Gonna chill down a bit next week and get back to my normal Flow :]