Flow: Flow complains about missing props annotation for exported classes with constructors

Created on 21 Apr 2016  Â·  14Comments  Â·  Source: facebook/flow

In this code, the TestPasses works fine, but flow complains about TestBroken with:

10: constructor(props) {super(props);}
^^^^^ parameter props. 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);}
}

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:

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 🎉

All 14 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

funtaps picture funtaps  Â·  3Comments

cubika picture cubika  Â·  3Comments

philikon picture philikon  Â·  3Comments

damncabbage picture damncabbage  Â·  3Comments

l2silver picture l2silver  Â·  3Comments