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

Issue:
TypeError: Cannot read property 'type' of undefined on Flow type
Hi,

since version 7.17.0 of eslint-plugin-react linting failed with:

```
TypeError: Cannot read property 'type' of undefined
Occurred while linting /Users/literat/Work/lmc/fp-admin/src/components/UI/Forms/Hidden.js:15
    at getKeyValue (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/ast.js:172:14)
    at /Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/propTypes.js:284:19
    at iterateProperties (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/propTypes.js:45:9)
    at declarePropTypesForObjectTypeAnnotation (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/propTypes.js:271:5)
    at markPropTypesAsDeclared (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/propTypes.js:474:33)
    at Object.markAnnotatedFunctionArgumentsAsDeclared (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/propTypes.js:620:7)
    at updatedRuleInstructions.<computed> (/Users/literat/Work/lmc/fp-admin/node_modules/eslint-plugin-react/lib/util/Components.js:883:43)
    at /Users/literat/Work/lmc/fp-admin/node_modules/eslint/lib/util/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/Users/literat/Work/lmc/fp-admin/node_modules/eslint/lib/util/safe-emitter.js:45:38)
```

Failed component is this one:

```javascript
// @flow
import React, { type Element } from 'react';

type THiddenProps = {|
  id?: string,
  name?: string,
  defaultValue?: string,
  ...any,
|};

const defaultProps = {
  defaultValue: '',
};

const Hidden = ({
  id,
  name,
  defaultValue,
  rest,
}: THiddenProps): Element<'input'> => (
  <input
    type="hidden"
    id={id}
    name={name}
    defaultValue={defaultValue}
    className="form-control"
    {...rest}
  />
);

Hidden.defaultProps = defaultProps;

export default Hidden;
```

If I remove or comment out `THiddenProps` everything works fine:

```javascript
// @flow
import React, { type Element } from 'react';

type THiddenProps = {|
  id?: string,
  name?: string,
  defaultValue?: string,
  ...any,
|};

const defaultProps = {
  defaultValue: '',
};

const Hidden = (
  { id, name, defaultValue, rest } /**: THiddenProps*/,
): Element<'input'> => (
  <input
    type="hidden"
    id={id}
    name={name}
    defaultValue={defaultValue}
    className="form-control"
    {...rest}
  />
);

Hidden.defaultProps = defaultProps;

export default Hidden;
```

Am I doing something wrong or is this a bug?

Thank you for your help.



Discussion:
Looks like a bug. a PR with a failing test case would be very helpful.



Patch:
diff --git a/lib/util/ast.js b/lib/util/ast.js
index 731a27330c..773cd65999 100644
--- a/lib/util/ast.js
+++ b/lib/util/ast.js
@@ -155,7 +155,7 @@ function stripQuotes(string) {
  * Retrieve the name of a key node
  * @param {Context} context The AST node with the key.
  * @param {ASTNode} node The AST node with the key.
- * @return {string} the name of the key
+ * @return {string | undefined} the name of the key
  */
 function getKeyValue(context, node) {
   if (node.type === 'ObjectTypeProperty') {
@@ -172,6 +172,9 @@ function getKeyValue(context, node) {
     return;
   }
   const key = node.key || node.argument;
+  if (!key) {
+    return;
+  }
   return key.type === 'Identifier' ? key.name : key.value;
 }
 


Test patch:
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index 7f1ec41835..e120d34f5f 100755
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -1650,6 +1650,17 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: parsers.BABEL_ESLINT
+    }, {
+      code: `
+        type FooProps = {
+          ...any,
+          ...42,
+        }
+        function Foo(props: FooProps) {
+          return <p />;
+        }
+      `,
+      parser: parsers.BABEL_ESLINT
     }, {
       code: [
         'type Person = {',