Repository: yannickcr/eslint-plugin-react
Pull request #1563 (2017-11-22 13:21:28)

Fix crash when using Unions in flow propTypes
This will fix the crash when using Union flowtypes for the following rules:

- `prop-types`
- `no-unused-prop-types`

The library already escapes early when facing a `typeNode` it doesn't recognize; this will escape early when we can't even figure out the `typeNode` because `UnionTypeAnnotation`s don't have an `annotation.id`.

This will not actually resolve the issue of using unions; it will simply prevent eslint from crashing.

Fixes issue https://github.com/yannickcr/eslint-plugin-react/issues/1468


Patch:
diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js
index f0c85596..d4135140 100644
--- a/lib/rules/no-unused-prop-types.js
+++ b/lib/rules/no-unused-prop-types.js
@@ -780,6 +780,10 @@ module.exports = {
           return declarePropTypesForObjectTypeAnnotation(annotation, declaredPropTypes);
         }
 
+        if (annotation.type === 'UnionTypeAnnotation') {
+          return true;
+        }
+
         const typeNode = typeScope(annotation.id.name);
 
         if (!typeNode) {
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index 7638959d..16d09d8e 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -726,6 +726,10 @@ module.exports = {
           return declarePropTypesForObjectTypeAnnotation(annotation, declaredPropTypes);
         }
 
+        if (annotation.type === 'UnionTypeAnnotation') {
+          return true;
+        }
+
         const typeNode = typeScope(annotation.id.name);
 
         if (!typeNode) {


Test patch:
diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js
index d4427aab..97ce57be 100644
--- a/tests/lib/rules/no-unused-prop-types.js
+++ b/tests/lib/rules/no-unused-prop-types.js
@@ -1097,6 +1097,28 @@ ruleTester.run('no-unused-prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
+    }, {
+      code: [
+        'type PropsUnionA = {',
+        '  a: string,',
+        '  b?: void,',
+        '};',
+        'type PropsUnionB = {',
+        '  a?: void,',
+        '  b: string,',
+        '};',
+        'type Props = {',
+        '  name: string,',
+        '} & (PropsUnionA | PropsUnionB);',
+        'class Hello extends React.Component {',
+        '  props: Props;',
+        '  render() {',
+        '    const {name} = this.props;',
+        '    return name;',
+        '  }',
+        '}'
+      ].join('\n'),
+      parser: 'babel-eslint'
     }, {
       code: [
         'Card.propTypes = {',
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index 9bc4223e..c16b7065 100644
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -1129,6 +1129,28 @@ ruleTester.run('prop-types', rule, {
         '}'
       ].join('\n'),
       parser: 'babel-eslint'
+    }, {
+      code: [
+        'type PropsUnionA = {',
+        '  a: string,',
+        '  b?: void,',
+        '};',
+        'type PropsUnionB = {',
+        '  a?: void,',
+        '  b: string,',
+        '};',
+        'type Props = {',
+        '  name: string,',
+        '} & (PropsUnionA | PropsUnionB);',
+        'class Hello extends React.Component {',
+        '  props: Props;',
+        '  render() {',
+        '    const {name} = this.props;',
+        '    return name;',
+        '  }',
+        '}'
+      ].join('\n'),
+      parser: 'babel-eslint'
     }, {
       code: [
         'Card.propTypes = {',