Repository: jsx-eslint/eslint-plugin-react (JavaScript)

Issue:
prop-types failing to parse flow type annotations
This presents in a very similar way to https://github.com/yannickcr/eslint-plugin-react/issues/1446, but it's happening in the prop-types rule, rather than no-unused-prop-types. It's related to flow type annotations, but unfortunately I don't have a good repro right now, I'll work on finding one. In the mean time, here it the stacktrace:

```
Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
    at iterateProperties (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:343:21)
    at declarePropTypesForObjectTypeAnnotation (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:702:7)
    at propTypes.types.some.annotation (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:737:16)
    at Array.some (native)
    at declarePropTypesForIntersectionTypeAnnotation (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:724:30)
    at markPropTypesAsDeclared (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:818:35)
    at Object.ClassDeclaration (/node_modules/eslint-plugin-react/lib/rules/prop-types.js:943:11)
    at Linter.updatedRuleInstructions.(anonymous function) (/node_modules/eslint-plugin-react/lib/util/Components.js:654:75)
    at emitOne (events.js:101:20)
    at Linter.emit (events.js:188:7)
    at NodeEventGenerator.applySelector (/node_modules/eslint/lib/util/node-event-generator.js:265:26)
    at NodeEventGenerator.applySelectors (/node_modules/eslint/lib/util/node-event-generator.js:294:22)
    at NodeEventGenerator.enterNode (/node_modules/eslint/lib/util/node-event-generator.js:308:14)
    at CodePathAnalyzer.enterNode (/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:602:23)
    at Traverser.enter (/node_modules/eslint/lib/linter.js:925:36)
    at Traverser.__execute (/node_modules/estraverse/estraverse.js:397:31)
    at Traverser.traverse (/node_modules/estraverse/estraverse.js:501:28)
```
  
Union error with Flow types
Seems that if I declare a union type for my props, this plugin dies:

```
$ eslint --fix src/ test/
Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
    at iterateProperties (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:363:22)
    at declarePropTypesForObjectTypeAnnotation (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:744:7)
    at propTypes.types.some.annotation (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:783:16)
    at Array.some (<anonymous>)
    at declarePropTypesForIntersectionTypeAnnotation (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:766:30)
    at markPropTypesAsDeclared (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:864:35)
    at Program:exit.classExpressions.forEach.node (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:1123:13)
    at Array.forEach (<anonymous>)
    at Program:exit (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint-plugin-react/lib/rules/prop-types.js:1121:26)
    at listeners.(anonymous function).forEach.listener (/Users/edwarddrapkin/projects/flex-mobile-head/node_modules/eslint/lib/util/safe-emitter.js:47:58)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

This type declaration triggers the error:

```

type Props = {
    style: typeof style & StyleObj,
    isValid: false,
    errorText: string
} | {
    style: typeof style & StyleObj,
    isValid: true,
    caption: string,
    icon?: Node
};

```

This one does not, but is less useful:

```
type Props = {
    style: typeof style,
    isValid: true,
    errorText?: string,
    caption?: string,
    icon?: Node
};
```

I'm on version 7.7.0.


Discussion:
Here is a fairly small repro case. Removing the `func` function fixes this, as does removing `Props & OP`, so there may be two separate issues here?

```js
// @flow
import * as React from 'react'

type Props = {}

const func = <OP: *>(arg) => arg

const hoc = <OP>() => () => {
  class Inner extends React.Component<Props & OP> {
    render() {
      return <div />
    }
  }
}
```
What version of flow are you using? What's "OP"?
I'm on flow 0.61, `OP` is a common abbreviation for "Own Props". This example is a bit confusing, because the hoc doesn't actually do anything. OP is commonly used with higher order components to denote the difference between props passed in props coming from redux or somewhere else.
Oh, and I'm on eslint 4.4.1 and eslint-plugin-react v7.5.1.
I am experiencing the same issue - it appears to be caused by using type intersections (`&`) as part of the prop types definition. 
Seems like a dup of #1446
Probably so; but I'd prefer to leave both open until we're sure :-)
Getting the same `eslint-plugin-react` error with this example:

``` javascript

type ReduxState = {bar: number};

const mapStateToProps = (state: ReduxState) => ({
    foo: state.bar,
})

// utility to extract the return type from a function
type ExtractReturn_<R, Fn: (...args: any[]) => R> = R;
type ExtractReturn<T> = ExtractReturn_<*, T>;

type PropsFromRedux = ExtractReturn<typeof mapStateToProps>;

type OwnProps = {
    baz: string,
}

// I want my Props to be {baz: string, foo: number}
type Props = PropsFromRedux & OwnProps;

const Component = (props. Props) => (
   <div>
       {props.baz}
       {props.foo}
   </div>
);

``` 





Patch:
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index bd66503f58..1895727984 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -360,7 +360,7 @@ module.exports = {
         and property value. (key, value) => void
      */
     function iterateProperties(properties, fn) {
-      if (properties.length && typeof fn === 'function') {
+      if (properties && properties.length && typeof fn === 'function') {
         for (let i = 0, j = properties.length; i < j; i++) {
           const node = properties[i];
           const key = getKeyValue(node);


Test patch:
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index 443d3bd10b..75d358426a 100644
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -1872,6 +1872,25 @@ ruleTester.run('prop-types', rule, {
       };
     `,
       parser: 'babel-eslint'
+    },
+    {
+      code: `
+      // @flow
+      import * as React from 'react'
+
+      type Props = {}
+
+      const func = <OP: *>(arg) => arg
+
+      const hoc = <OP>() => () => {
+        class Inner extends React.Component<Props & OP> {
+          render() {
+            return <div />
+          }
+        }
+      }
+    `,
+      parser: 'babel-eslint'
     }
   ],
 
@@ -3627,6 +3646,38 @@ ruleTester.run('prop-types', rule, {
         message: '\'fooBar\' is missing in props validation'
       }],
       parser: 'babel-eslint'
+    },
+    {
+      code: `
+      type ReduxState = {bar: number};
+
+      const mapStateToProps = (state: ReduxState) => ({
+          foo: state.bar,
+      });
+      // utility to extract the return type from a function
+      type ExtractReturn_<R, Fn: (...args: any[]) => R> = R;
+      type ExtractReturn<T> = ExtractReturn_<*, T>;
+
+      type PropsFromRedux = ExtractReturn<typeof mapStateToProps>;
+
+      type OwnProps = {
+          baz: string,
+      }
+
+      // I want my Props to be {baz: string, foo: number}
+      type Props = PropsFromRedux & OwnProps;
+
+      const Component = (props: Props) => (
+        <div>
+            {props.baz}
+            {props.bad}
+        </div>
+      );
+    `,
+      errors: [{
+        message: '\'bad\' is missing in props validation'
+      }],
+      parser: 'babel-eslint'
     }
   ]
 });