Flow 0.100 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
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).
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:
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.
function usingSealed(x: Sealed) {
// does things
}
usingSealed({ foo: 'foo', bar: 'bar' }) // ok
Not so when the functions are expecting exact objects:
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:
// destructuring on function parameter
function goodUsingSealed({ foo }: Sealed) { // ok
// does things
}
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:
// fixed in 0.100
function badUsingSealed({ foo, bar }: Sealed) { // error after 0.100
// does things
}
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 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
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
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).
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:
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 explains it very well.
🐶 Till next time
Flow 0.101 is already out and I'm falling behind 😭 It's JSConf.Asia at home now. Gonna chill down a bit next week and get back to my normal Flow :]
Top comments (0)