Repository: brigand/babel-plugin-flow-react-proptypes (js)

Issue:
Why are element types of arrays not marked required?
The Flow type `number[]` denotes a list of non-nullable numbers:
```js
const a: number[] = [1, 2, 3];  // okay
const b: number[] = [1, null, 3];  // type error: null is incompatible with number
```
This plugin translates such a typedef into `PropTypes.arrayOf(PropTypes.number).isRequired`. But this does not require that the elements be non-null:
```js
class App extends Component {
    render() {
        return <Test values={[1, null, 3]} />;  // no error
    }
}
class Test extends Component {
    static propTypes = {
        values: PropTypes.arrayOf(PropTypes.number).isRequired,
    }
    render() {
        return null;
    }
}
```
It seems that:
  * `number[]` should become `PropTypes.arrayOf(PropTypes.number.isRequired).isRequired`, while
  * `(?number)[]` should become `PropTypes.arrayOf(PropTypes.number).isRequired`.

Of course, this should apply uniformly to all element types, not just `number`.

Any reasons for this to not be the case?

(Note: When #182 is merged, this should apply equally to `objectOf`. The semantics of `objectOf` as proposed in #182 also use the non-`isRequired` form, just to conform to the standard set by `arrayOf` as described above.)

Pull request:
Allow `arrayOf`/`objectOf` elements to be required
Summary:
Fixes #183; see rationale there.

Test Plan:
The code change to `convertToPropTypes` is sufficient to fix the
`generic-array` and `objectof` tests, including the test modified in
this commit:

    yarn test objectof generic-array

Obviously, this is a wide-reaching change, so several other snapshots
were invalidated. I generated them, and manually inspected the results
to ensure that the changes are correct. They are, as far as I can tell;
the arrays of external types are harder to read, but by comparison with
surrounding code they seem okay to me.

wchargin-branch: arrayof-objectof-elements-required

Patch:
diff --git a/README.md b/README.md
index 7e291ca..31f9e14 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ Foo.propTypes = {
   a_number: bpfrp_PropTypes.number.isRequired,
   a_boolean: bpfrp_PropTypes.bool.isRequired,
   a_generic_object: bpfrp_PropTypes.object.isRequired,
-  array_of_strings: bpfrp_PropTypes.arrayOf(bpfrp_PropTypes.string).isRequired,
+  array_of_strings: bpfrp_PropTypes.arrayOf(bpfrp_PropTypes.string.isRequired).isRequired,
   instance_of_Bar: function () {
     return (typeof Bar === 'function' ? bpfrp_PropTypes.instanceOf(Bar).isRequired : bpfrp_PropTypes.any.isRequired).apply(this, arguments);
   },
diff --git a/src/convertToPropTypes.js b/src/convertToPropTypes.js
index 6477d6a..37a3489 100644
--- a/src/convertToPropTypes.js
+++ b/src/convertToPropTypes.js
@@ -116,6 +116,7 @@ export default function convertToPropTypes(node, importedTypes, internalTypes) {
       const indexer = node.indexers[0];
       const subnode = indexer.value;
       const subresult = convertToPropTypes(subnode, importedTypes, internalTypes);
+      subresult.isRequired = !subresult.optional;
       resultPropType = {type: 'objectOf', of: subresult};
     }
     else {
@@ -278,7 +279,9 @@ export default function convertToPropTypes(node, importedTypes, internalTypes) {
         resultPropType = {type: 'node'};
       }
       else if (arrayType) {
-        resultPropType = {type: 'arrayOf', of: convertToPropTypes(arrayType, importedTypes, internalTypes)};
+        const elementType = convertToPropTypes(arrayType, importedTypes, internalTypes);
+        elementType.isRequired = !elementType.optional;
+        resultPropType = {type: 'arrayOf', of: elementType};
       }
     }
     else if (node.type === 'GenericTypeAnnotation' &&


Test patch:
diff --git a/src/__tests__/__snapshots__/array-shorthand-test.js.snap b/src/__tests__/__snapshots__/array-shorthand-test.js.snap
index 85abb93..bed3e87 100644
--- a/src/__tests__/__snapshots__/array-shorthand-test.js.snap
+++ b/src/__tests__/__snapshots__/array-shorthand-test.js.snap
@@ -41,7 +41,7 @@ var C = function (_React$Component) {
 }(React.Component);
 
 C.propTypes = {
-  as: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired
+  as: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired
 };
 exports.default = C;"
 `;
diff --git a/src/__tests__/__snapshots__/arrayof-objectof-required-test.js.snap b/src/__tests__/__snapshots__/arrayof-objectof-required-test.js.snap
new file mode 100644
index 0000000..ff83b9a
--- /dev/null
+++ b/src/__tests__/__snapshots__/arrayof-objectof-required-test.js.snap
@@ -0,0 +1,99 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`objectOf 1`] = `
+"'use strict';
+
+Object.defineProperty(exports, \\"__esModule\\", {
+  value: true
+});
+
+var _propTypes = require('prop-types');
+
+var _propTypes2 = _interopRequireDefault(_propTypes);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\\"Cannot call a class as a function\\"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\\"this hasn't been initialised - super() hasn't been called\\"); } return call && (typeof call === \\"object\\" || typeof call === \\"function\\") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== \\"function\\" && superClass !== null) { throw new TypeError(\\"Super expression must either be null or a function, not \\" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var React = require('react');
+
+var Foo = function (_React$Component) {
+  _inherits(Foo, _React$Component);
+
+  function Foo() {
+    _classCallCheck(this, Foo);
+
+    return _possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).apply(this, arguments));
+  }
+
+  return Foo;
+}(React.Component);
+
+Foo.propTypes = {
+  arrayAnnotationOfNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number.isRequired).isRequired,
+  genericArrayOfNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number.isRequired).isRequired,
+  objectOfNumbers: _propTypes2.default.objectOf(_propTypes2.default.number.isRequired).isRequired,
+  arrayAnnotationOfOptionalNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired,
+  genericArrayOfOptionalNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired,
+  objectOfOptionalNumbers: _propTypes2.default.objectOf(_propTypes2.default.number).isRequired,
+  optionalArrayAnnotationOfNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number.isRequired),
+  optionalGenericArrayOfNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number.isRequired),
+  optionalObjectOfNumbers: _propTypes2.default.objectOf(_propTypes2.default.number.isRequired),
+  optionalArrayAnnotationOfOptionalNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number),
+  optionalGenericArrayOfOptionalNumbers: _propTypes2.default.arrayOf(_propTypes2.default.number),
+  optionalObjectOfOptionalNumbers: _propTypes2.default.objectOf(_propTypes2.default.number),
+  arrayAnnotationOfComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired).isRequired,
+  genericArrayOfComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired).isRequired,
+  objectOfComplexes: _propTypes2.default.objectOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired).isRequired,
+  arrayAnnotationOfOptionalComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  })).isRequired,
+  genericArrayOfOptionalComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  })).isRequired,
+  objectOfOptionalComplexes: _propTypes2.default.objectOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  })).isRequired,
+  optionalArrayAnnotationOfComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired),
+  optionalGenericArrayOfComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired),
+  optionalObjectOfComplexes: _propTypes2.default.objectOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }).isRequired),
+  optionalArrayAnnotationOfOptionalComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  })),
+  optionalGenericArrayOfOptionalComplexes: _propTypes2.default.arrayOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  })),
+  optionalObjectOfOptionalComplexes: _propTypes2.default.objectOf(_propTypes2.default.shape({
+    imag: _propTypes2.default.number.isRequired,
+    real: _propTypes2.default.number.isRequired
+  }))
+};
+exports.default = Foo;"
+`;
diff --git a/src/__tests__/__snapshots__/basic-test.js.snap b/src/__tests__/__snapshots__/basic-test.js.snap
index b0e2ab2..68b50c8 100644
--- a/src/__tests__/__snapshots__/basic-test.js.snap
+++ b/src/__tests__/__snapshots__/basic-test.js.snap
@@ -45,7 +45,7 @@ Foo.propTypes = {
   a_number: _propTypes2.default.number.isRequired,
   a_boolean: _propTypes2.default.bool.isRequired,
   a_generic_object: _propTypes2.default.object.isRequired,
-  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired,
+  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired,
   instance_of_Bar: function instance_of_Bar() {
     return (typeof Bar === 'function' ? _propTypes2.default.instanceOf(Bar).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
   },
diff --git a/src/__tests__/__snapshots__/children-test.js.snap b/src/__tests__/__snapshots__/children-test.js.snap
index f33ed51..4c62bd1 100644
--- a/src/__tests__/__snapshots__/children-test.js.snap
+++ b/src/__tests__/__snapshots__/children-test.js.snap
@@ -22,7 +22,7 @@ function Foo(props) {
 Foo.propTypes = {
   children: _propTypes2.default.node.isRequired,
   children2: _propTypes2.default.arrayOf(function () {
-    return (typeof Element === 'function' ? _propTypes2.default.instanceOf(Element) : _propTypes2.default.any).apply(this, arguments);
+    return (typeof Element === 'function' ? _propTypes2.default.instanceOf(Element).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
   }).isRequired,
   children3: function children3() {
     return (typeof Element === 'function' ? _propTypes2.default.instanceOf(Element).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
diff --git a/src/__tests__/__snapshots__/generic-array.js.snap b/src/__tests__/__snapshots__/generic-array.js.snap
index 6d4b2a6..4966151 100644
--- a/src/__tests__/__snapshots__/generic-array.js.snap
+++ b/src/__tests__/__snapshots__/generic-array.js.snap
@@ -36,7 +36,7 @@ var ArrayTest = function (_React$Component) {
 }(_react2.default.Component);
 
 ArrayTest.propTypes = {
-  foo: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired
+  foo: _propTypes2.default.arrayOf(_propTypes2.default.number.isRequired).isRequired
 };
 exports.default = ArrayTest;"
 `;
diff --git a/src/__tests__/__snapshots__/import-and-loops-test.js.snap b/src/__tests__/__snapshots__/import-and-loops-test.js.snap
index 2e8dd80..2bf30f0 100644
--- a/src/__tests__/__snapshots__/import-and-loops-test.js.snap
+++ b/src/__tests__/__snapshots__/import-and-loops-test.js.snap
@@ -23,7 +23,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
 var bpfrpt_proptype_T = {
     flag: _propTypes2.default.bool.isRequired,
     list: _propTypes2.default.arrayOf(function () {
-        return (typeof _types.bpfrpt_proptype_ExternalType === 'function' ? _types.bpfrpt_proptype_ExternalType : _propTypes2.default.shape(_types.bpfrpt_proptype_ExternalType)).apply(this, arguments);
+        return (typeof _types.bpfrpt_proptype_ExternalType === 'function' ? _types.bpfrpt_proptype_ExternalType.isRequired ? _types.bpfrpt_proptype_ExternalType.isRequired : _types.bpfrpt_proptype_ExternalType : _propTypes2.default.shape(_types.bpfrpt_proptype_ExternalType).isRequired).apply(this, arguments);
     }).isRequired
 };
 
diff --git a/src/__tests__/__snapshots__/objectof-test.js.snap b/src/__tests__/__snapshots__/objectof-test.js.snap
index 9b70a1c..a50a56c 100644
--- a/src/__tests__/__snapshots__/objectof-test.js.snap
+++ b/src/__tests__/__snapshots__/objectof-test.js.snap
@@ -39,11 +39,11 @@ Foo.propTypes = {
     real: _propTypes2.default.number.isRequired,
     imag: _propTypes2.default.number.isRequired
   }).isRequired,
-  manyNumbers: _propTypes2.default.objectOf(_propTypes2.default.number).isRequired,
+  manyNumbers: _propTypes2.default.objectOf(_propTypes2.default.number.isRequired).isRequired,
   manyComplex: _propTypes2.default.objectOf(_propTypes2.default.shape({
     real: _propTypes2.default.number.isRequired,
     imag: _propTypes2.default.number.isRequired
-  })).isRequired
+  }).isRequired).isRequired
 };
 exports.default = Foo;"
 `;
diff --git a/src/__tests__/__snapshots__/real4-test.js.snap b/src/__tests__/__snapshots__/real4-test.js.snap
index b713292..035b033 100644
--- a/src/__tests__/__snapshots__/real4-test.js.snap
+++ b/src/__tests__/__snapshots__/real4-test.js.snap
@@ -22,18 +22,18 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
 
 var bpfrpt_proptype_jpopunderPostResult = {
     items: _propTypes2.default.arrayOf(function () {
-        return (typeof _JLCommon.bpfrpt_proptype_Job === 'function' ? _JLCommon.bpfrpt_proptype_Job : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_Job)).apply(this, arguments);
+        return (typeof _JLCommon.bpfrpt_proptype_Job === 'function' ? _JLCommon.bpfrpt_proptype_Job.isRequired ? _JLCommon.bpfrpt_proptype_Job.isRequired : _JLCommon.bpfrpt_proptype_Job : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_Job).isRequired).apply(this, arguments);
     }).isRequired,
     adPartners: _propTypes2.default.arrayOf(function () {
-        return (typeof _JLCommon.bpfrpt_proptype_AdPartner === 'function' ? _JLCommon.bpfrpt_proptype_AdPartner : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_AdPartner)).apply(this, arguments);
+        return (typeof _JLCommon.bpfrpt_proptype_AdPartner === 'function' ? _JLCommon.bpfrpt_proptype_AdPartner.isRequired ? _JLCommon.bpfrpt_proptype_AdPartner.isRequired : _JLCommon.bpfrpt_proptype_AdPartner : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_AdPartner).isRequired).apply(this, arguments);
     }).isRequired
 };
 var bpfrpt_proptype_searchPostResult = {
     items: _propTypes2.default.arrayOf(function () {
-        return (typeof _JLCommon.bpfrpt_proptype_Job === 'function' ? _JLCommon.bpfrpt_proptype_Job : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_Job)).apply(this, arguments);
+        return (typeof _JLCommon.bpfrpt_proptype_Job === 'function' ? _JLCommon.bpfrpt_proptype_Job.isRequired ? _JLCommon.bpfrpt_proptype_Job.isRequired : _JLCommon.bpfrpt_proptype_Job : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_Job).isRequired).apply(this, arguments);
     }).isRequired,
     seoText: _propTypes2.default.arrayOf(function () {
-        return (typeof _JLCommon.bpfrpt_proptype_SeoText === 'function' ? _JLCommon.bpfrpt_proptype_SeoText : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_SeoText)).apply(this, arguments);
+        return (typeof _JLCommon.bpfrpt_proptype_SeoText === 'function' ? _JLCommon.bpfrpt_proptype_SeoText.isRequired ? _JLCommon.bpfrpt_proptype_SeoText.isRequired : _JLCommon.bpfrpt_proptype_SeoText : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_SeoText).isRequired).apply(this, arguments);
     }),
     query: function query() {
         return (typeof _jobliftQueryParser.bpfrpt_proptype_SearchQuery === 'function' ? _jobliftQueryParser.bpfrpt_proptype_SearchQuery.isRequired ? _jobliftQueryParser.bpfrpt_proptype_SearchQuery.isRequired : _jobliftQueryParser.bpfrpt_proptype_SearchQuery : _propTypes2.default.shape(_jobliftQueryParser.bpfrpt_proptype_SearchQuery).isRequired).apply(this, arguments);
@@ -46,7 +46,7 @@ var bpfrpt_proptype_searchPostResult = {
         key: _propTypes2.default.number.isRequired,
         amount: _propTypes2.default.number.isRequired,
         translation: _propTypes2.default.string.isRequired
-    })))
+    }).isRequired).isRequired)
 };
 
 // eslint-disable-next-line
@@ -54,7 +54,7 @@ var bpfrpt_proptype_searchPostResult = {
 var bpfrpt_proptype_jobalertMeGetResult = {
     description: _propTypes2.default.string.isRequired,
     jobalerts: _propTypes2.default.arrayOf(function () {
-        return (typeof _JLCommon.bpfrpt_proptype_JobAlert === 'function' ? _JLCommon.bpfrpt_proptype_JobAlert : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_JobAlert)).apply(this, arguments);
+        return (typeof _JLCommon.bpfrpt_proptype_JobAlert === 'function' ? _JLCommon.bpfrpt_proptype_JobAlert.isRequired ? _JLCommon.bpfrpt_proptype_JobAlert.isRequired : _JLCommon.bpfrpt_proptype_JobAlert : _propTypes2.default.shape(_JLCommon.bpfrpt_proptype_JobAlert).isRequired).apply(this, arguments);
     }).isRequired
 };
 
@@ -69,7 +69,7 @@ var bpfrpt_proptype_joblocationReverseLookupGetResult = {
 var bpfrpt_proptype_joblocationSuggestionGetResult = {
     suggestions: _propTypes2.default.arrayOf(_propTypes2.default.shape({
         value: _propTypes2.default.string.isRequired
-    })).isRequired
+    }).isRequired).isRequired
 };
 
 // api/joblocation-suggestion
@@ -78,7 +78,7 @@ var bpfrpt_proptype_jobsearchSuggestionGetResult = {
     suggestions: _propTypes2.default.arrayOf(_propTypes2.default.shape({
         value: _propTypes2.default.string.isRequired,
         numJobs: _propTypes2.default.number
-    })).isRequired
+    }).isRequired).isRequired
 };
 
 // api/jobsearch-suggestion
@@ -87,13 +87,13 @@ var bpfrpt_proptype_freqSearchSuggestionGetResult = {
     suggestions: _propTypes2.default.arrayOf(_propTypes2.default.shape({
         value: _propTypes2.default.string.isRequired,
         numJobs: _propTypes2.default.number.isRequired
-    })).isRequired
+    }).isRequired).isRequired
 };
 
 // api/jobsearch-suggestion/popular
 
 var bpfrpt_proptype_statisticalDataGetResult = {
-    keys: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired,
+    keys: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired,
     data: _propTypes2.default.object.isRequired
 };
 
@@ -124,9 +124,9 @@ var bpfrpt_proptype_loginPostResult = {
     lastName: _propTypes2.default.string.isRequired,
     localAccounts: _propTypes2.default.arrayOf(_propTypes2.default.shape({
         email: _propTypes2.default.string.isRequired
-    })).isRequired,
-    socialAccounts: _propTypes2.default.arrayOf(_propTypes2.default.object).isRequired,
-    uniqueEmails: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired,
+    }).isRequired).isRequired,
+    socialAccounts: _propTypes2.default.arrayOf(_propTypes2.default.object.isRequired).isRequired,
+    uniqueEmails: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired,
     uuid: _propTypes2.default.string.isRequired
 };
 
@@ -137,7 +137,7 @@ var bpfrpt_proptype_directApplyDraftGet = _DirectApply.bpfrpt_proptype_DirectApp
 // api/direct-apply/offer/<jobofferid>/draft
 
 var bpfrpt_proptype_directApplyRecentFilesGet = _propTypes2.default.arrayOf(function () {
-    return (typeof _DirectApply.bpfrpt_proptype_DirectApplyFile === 'function' ? _DirectApply.bpfrpt_proptype_DirectApplyFile : _propTypes2.default.shape(_DirectApply.bpfrpt_proptype_DirectApplyFile)).apply(this, arguments);
+    return (typeof _DirectApply.bpfrpt_proptype_DirectApplyFile === 'function' ? _DirectApply.bpfrpt_proptype_DirectApplyFile.isRequired ? _DirectApply.bpfrpt_proptype_DirectApplyFile.isRequired : _DirectApply.bpfrpt_proptype_DirectApplyFile : _propTypes2.default.shape(_DirectApply.bpfrpt_proptype_DirectApplyFile).isRequired).apply(this, arguments);
 });
 
 // api/direct-apply/files/recent
diff --git a/src/__tests__/__snapshots__/stateless-inline-test.js.snap b/src/__tests__/__snapshots__/stateless-inline-test.js.snap
index 2b59bb9..31fce46 100644
--- a/src/__tests__/__snapshots__/stateless-inline-test.js.snap
+++ b/src/__tests__/__snapshots__/stateless-inline-test.js.snap
@@ -29,7 +29,7 @@ Foo.propTypes = {
   a_number: _propTypes2.default.number.isRequired,
   a_boolean: _propTypes2.default.bool.isRequired,
   a_generic_object: _propTypes2.default.object.isRequired,
-  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired,
+  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired,
   instance_of_Bar: function instance_of_Bar() {
     return (typeof Bar === 'function' ? _propTypes2.default.instanceOf(Bar).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
   },
diff --git a/src/__tests__/__snapshots__/stateless-test.js.snap b/src/__tests__/__snapshots__/stateless-test.js.snap
index 7ece5da..a3c1e18 100644
--- a/src/__tests__/__snapshots__/stateless-test.js.snap
+++ b/src/__tests__/__snapshots__/stateless-test.js.snap
@@ -28,7 +28,7 @@ Foo.propTypes = {
   a_number: _propTypes2.default.number.isRequired,
   a_boolean: _propTypes2.default.bool.isRequired,
   a_generic_object: _propTypes2.default.object.isRequired,
-  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string).isRequired,
+  array_of_strings: _propTypes2.default.arrayOf(_propTypes2.default.string.isRequired).isRequired,
   instance_of_Bar: function instance_of_Bar() {
     return (typeof Bar === 'function' ? _propTypes2.default.instanceOf(Bar).isRequired : _propTypes2.default.any.isRequired).apply(this, arguments);
   },
diff --git a/src/__tests__/arrayof-objectof-required-test.js b/src/__tests__/arrayof-objectof-required-test.js
new file mode 100644
index 0000000..06deff9
--- /dev/null
+++ b/src/__tests__/arrayof-objectof-required-test.js
@@ -0,0 +1,55 @@
+const babel = require('babel-core');
+const content = `
+var React = require('react');
+
+type Complex = {
+  imag: number;
+  real: number;
+}
+type FooProps = {
+  arrayAnnotationOfNumbers: number[];
+  genericArrayOfNumbers: Array<number>;
+  objectOfNumbers: {[name: string]: number};
+
+  arrayAnnotationOfOptionalNumbers: (?number)[];
+  genericArrayOfOptionalNumbers: Array<?number>;
+  objectOfOptionalNumbers: {[name: string]: ?number};
+
+  optionalArrayAnnotationOfNumbers: ?number[];
+  optionalGenericArrayOfNumbers: ?Array<number>;
+  optionalObjectOfNumbers: ?{[name: string]: number};
+
+  optionalArrayAnnotationOfOptionalNumbers: ?(?number)[];
+  optionalGenericArrayOfOptionalNumbers: ?Array<?number>;
+  optionalObjectOfOptionalNumbers: ?{[name: string]: ?number};
+
+  arrayAnnotationOfComplexes: Complex[];
+  genericArrayOfComplexes: Array<Complex>;
+  objectOfComplexes: {[name: string]: Complex};
+
+  arrayAnnotationOfOptionalComplexes: (?Complex)[];
+  genericArrayOfOptionalComplexes: Array<?Complex>;
+  objectOfOptionalComplexes: {[name: string]: ?Complex};
+
+  optionalArrayAnnotationOfComplexes: ?Complex[];
+  optionalGenericArrayOfComplexes: ?Array<Complex>;
+  optionalObjectOfComplexes: ?{[name: string]: Complex};
+
+  optionalArrayAnnotationOfOptionalComplexes: ?(?Complex)[];
+  optionalGenericArrayOfOptionalComplexes: ?Array<?Complex>;
+  optionalObjectOfOptionalComplexes: ?{[name: string]: ?Complex};
+}
+
+export default class Foo extends React.Component {
+  props: FooProps
+}
+`;
+
+it('objectOf', () => {
+  const res = babel.transform(content, {
+    babelrc: false,
+    presets: ['es2015', 'stage-1', 'react'],
+    plugins: ['syntax-flow', require('../')],
+  }).code;
+  expect(res).toMatchSnapshot();
+});