In this code, the TestPasses
works fine, but flow complains about TestBroken
with:
10: constructor(props) {super(props);}
^^^^^ parameterprops
. Missing annotation
The only difference is in the export
keyword. From my reading of the docs, I'd assume both should work fine in the presence of the props: {}
. The minimal repro case needs (1) to be exported, and (2) a constructor that takes props. It also errors on non-empty prop type definitions as well.
/* @flow */
'use strict';
import React from 'react-native';
class TestPasses extends React.Component {
props: {};
constructor(props) {super(props);}
}
export class TestBroken extends React.Component {
props: {};
constructor(props) {super(props);}
}
Oh, and this is happening with Flow 0.23.0, and occurs on a fresh 'flow init'.
Also occurs on this slightly more minimal test case (didn't know if it was special-casing React Components for the props
type definitions):
/* @flow */
'use strict';
class TestPasses extends Object {
props: {};
constructor(props) {}
}
export class TestBroken extends Object {
props: {};
constructor(props) {}
}
Unless this is not a bug, and I need to define the props as an actual Type, and then use it to annotate the constructor's props? (As seen in http://sitr.us/2015/05/31/type-checking-react-with-flow.html )
The official Flow docs page for React seemed to suggest my approach above was correct, though... ( ie, towards the bottom of http://flowtype.org/docs/react.html in the "Defining components as React.Component subclasses" section (which incidentally, has a header-formatting issue ))
+1
+1
I'm also using react native, if that makes any difference, but I'm using import React from 'react'
separate from the RN imports.
+1
+1
+1
Flow uses type inference extensively for local contexts, which is why you can have a class that doesn’t annotate the props parameter in the constructor or other lifecycle methods. However, Flow is stricter for any exported modules in order to avoid hard-to-find issues or bugs across different files. Specifically, from Type Annotation vs. Inference:
Exported classes must annotate their method signatures - parameter and return types - in addition to field declarations
I also struggled with this before finding the part of the docs that I quoted above, especially because, as @mikelambert pointed out, in the React part of the docs, there’s an example of a component class where constructor(props)
is not annotated. The class isn’t exported, so it will work as is, but it seems like a pretty useless example, because if anyone tries to implement it in an actual project, they will immediately get “Missing annotation” errors. I think it would be far better to have the example define a Props
type and use it to annotate the class props
instance property and the constructor props
parameter.
Update: Docs example mentioned above now uses a Props
type to annotate the class props
instance and constructor props
parameter 🎉
I think this issue can be closed.
The referenced change was in /docs/react.html
while https://flow.org/en/docs/frameworks/react/ still uses the "old style" or am I missing something?
Doc is not up-to-date, indeed.
The doc was rewritten and extended with a number of improvements, but that also included removing the method signature annotations from the default example. @thejameskyle As best as I can tell, you were primarily responsible for rewriting that doc. Would you be open to changing the default example to mention the potential pitfall of exporting a React component having only specified the props:
field type annotation? Or changing that example to have a constructor
with its props
argument annotated? I notice that even the second example in the section about annotating state
, which includes a constructor
, does not annotate the props
arg.
More generally, I think the point of this issue is that the React doc should be written with the assumption that most people will be needing to type their React components in a context where those components will then be exported, and so the examples should be authored in such a way as to support that use case out of the box.
I'm having a similar issue following the ref functions guide. The example shown in the docs works fine as long as you aren't exporting the component class - as soon as you do you get a series of flow errors that I can't figure out how to resolve.
Most helpful comment
Flow uses type inference extensively for local contexts, which is why you can have a class that doesn’t annotate the props parameter in the constructor or other lifecycle methods. However, Flow is stricter for any exported modules in order to avoid hard-to-find issues or bugs across different files. Specifically, from Type Annotation vs. Inference:
I also struggled with this before finding the part of the docs that I quoted above, especially because, as @mikelambert pointed out, in the React part of the docs, there’s an example of a component class where
constructor(props)
is not annotated. The class isn’t exported, so it will work as is, but it seems like a pretty useless example, because if anyone tries to implement it in an actual project, they will immediately get “Missing annotation” errors. I think it would be far better to have the example define aProps
type and use it to annotate the classprops
instance property and the constructorprops
parameter.Update: Docs example mentioned above now uses a
Props
type to annotate the classprops
instance and constructorprops
parameter 🎉