@@ -32,13 +32,19 @@ function isSuperTypeParameterPropsDeclaration(node) {
3232 * @param {Object[] } properties Array of properties to iterate.
3333 * @param {Function } fn Function to call on each property, receives property key
3434 and property value. (key, value) => void
35+ * @param {Function } [handleSpreadFn] Function to call on each ObjectTypeSpreadProperty, receives the
36+ argument
3537 */
36- function iterateProperties ( context , properties , fn ) {
38+ function iterateProperties ( context , properties , fn , handleSpreadFn ) {
3739 if ( properties && properties . length && typeof fn === 'function' ) {
3840 for ( let i = 0 , j = properties . length ; i < j ; i ++ ) {
3941 const node = properties [ i ] ;
4042 const key = getKeyValue ( context , node ) ;
4143
44+ if ( node . type === 'ObjectTypeSpreadProperty' && typeof handleSpreadFn === 'function' ) {
45+ handleSpreadFn ( node . argument ) ;
46+ }
47+
4248 const value = node . value ;
4349 fn ( key , value , node ) ;
4450 }
@@ -121,30 +127,41 @@ module.exports = function propTypesInstructions(context, components, utils) {
121127 } ,
122128
123129 ObjectTypeAnnotation ( annotation , parentName , seen ) {
124- let containsObjectTypeSpread = false ;
130+ let containsUnresolvedObjectTypeSpread = false ;
131+ let containsSpread = false ;
125132 const containsIndexers = Boolean ( annotation . indexers && annotation . indexers . length ) ;
126133 const shapeTypeDefinition = {
127134 type : 'shape' ,
128135 children : { }
129136 } ;
130137 iterateProperties ( context , annotation . properties , ( childKey , childValue , propNode ) => {
131138 const fullName = [ parentName , childKey ] . join ( '.' ) ;
132- if ( ! childKey && ! childValue ) {
133- containsObjectTypeSpread = true ;
134- } else {
139+ if ( childKey || childValue ) {
135140 const types = buildTypeAnnotationDeclarationTypes ( childValue , fullName , seen ) ;
136141 types . fullName = fullName ;
137142 types . name = childKey ;
138143 types . node = propNode ;
139144 types . isRequired = ! childValue . optional ;
140145 shapeTypeDefinition . children [ childKey ] = types ;
141146 }
147+ } ,
148+ ( spreadNode ) => {
149+ const key = getKeyValue ( context , spreadNode ) ;
150+ const types = buildTypeAnnotationDeclarationTypes ( spreadNode , key , seen ) ;
151+ if ( ! types . children ) {
152+ containsUnresolvedObjectTypeSpread = true ;
153+ } else {
154+ Object . assign ( shapeTypeDefinition , types . children ) ;
155+ }
156+ containsSpread = true ;
142157 } ) ;
143158
144159 // Mark if this shape has spread or an indexer. We will know to consider all props from this shape as having propTypes,
145160 // but still have the ability to detect unused children of this shape.
146- shapeTypeDefinition . containsSpread = containsObjectTypeSpread ;
161+ shapeTypeDefinition . containsUnresolvedSpread = containsUnresolvedObjectTypeSpread ;
147162 shapeTypeDefinition . containsIndexers = containsIndexers ;
163+ // Deprecated: containsSpread is not used anymore in the codebase, ensure to keep API backward compatibility
164+ shapeTypeDefinition . containsSpread = containsSpread ;
148165
149166 return shapeTypeDefinition ;
150167 } ,
@@ -241,7 +258,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
241258 }
242259
243260 /**
244- * Marks all props found inside ObjectTypeAnnotaiton as declared.
261+ * Marks all props found inside ObjectTypeAnnotation as declared.
245262 *
246263 * Modifies the declaredProperties object
247264 * @param {ASTNode } propTypes
@@ -253,7 +270,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
253270
254271 iterateProperties ( context , propTypes . properties , ( key , value , propNode ) => {
255272 if ( ! value ) {
256- ignorePropsValidation = true ;
273+ ignorePropsValidation = ignorePropsValidation || propNode . type !== 'ObjectTypeSpreadProperty' ;
257274 return ;
258275 }
259276
@@ -263,6 +280,15 @@ module.exports = function propTypesInstructions(context, components, utils) {
263280 types . node = propNode ;
264281 types . isRequired = ! propNode . optional ;
265282 declaredPropTypes [ key ] = types ;
283+ } , ( spreadNode ) => {
284+ const key = getKeyValue ( context , spreadNode ) ;
285+ const spreadAnnotation = getInTypeScope ( key ) ;
286+ if ( ! spreadAnnotation ) {
287+ ignorePropsValidation = true ;
288+ } else {
289+ const spreadIgnoreValidation = declarePropTypesForObjectTypeAnnotation ( spreadAnnotation , declaredPropTypes ) ;
290+ ignorePropsValidation = ignorePropsValidation || spreadIgnoreValidation ;
291+ }
266292 } ) ;
267293
268294 return ignorePropsValidation ;
0 commit comments