@@ -18,7 +18,9 @@ import isUnreachableFlowType from '../utils/isUnreachableFlowType';
1818import  recast  from  'recast' ; 
1919import  resolveToValue  from  '../utils/resolveToValue' ; 
2020
21- var  { types : { namedTypes : types } }  =  recast ; 
21+ const  { types : { namedTypes : types } }  =  recast ; 
22+ 
23+ const  supportedUtilityTypes  =  new  Set ( [ '$Exact' ,  '$ReadOnly' ] ) ; 
2224
2325/** 
2426 * Given an React component (stateless or class) tries to find the 
@@ -52,7 +54,9 @@ export default (path: NodePath): ?NodePath  => {
5254    typePath  =  getTypeAnnotation ( param ) ; 
5355  } 
5456
55-   if  ( typePath  &&  types . GenericTypeAnnotation . check ( typePath . node ) )  { 
57+   if  ( typePath  &&  isSupportedUtilityType ( typePath ) )  { 
58+     typePath  =  unwrapUtilityType ( typePath ) ; 
59+   }  else  if  ( typePath  &&  types . GenericTypeAnnotation . check ( typePath . node ) )  { 
5660    typePath  =  resolveToValue ( typePath . get ( 'id' ) ) ; 
5761    if  ( 
5862      ! typePath  || 
@@ -93,7 +97,9 @@ export function applyToFlowTypeProperties(
9397function  resolveGenericTypeAnnotation ( path : NodePath ) : ?NodePath  { 
9498  // If the node doesn't have types or properties, try to get the type. 
9599  let  typePath : ?NodePath ; 
96-   if  ( path  &&  types . GenericTypeAnnotation . check ( path . node ) )  { 
100+   if  ( path  &&  isSupportedUtilityType ( path ) )  { 
101+     typePath  =  unwrapUtilityType ( path ) ; 
102+   }  else  if ( path  &&  types . GenericTypeAnnotation . check ( path . node ) )  { 
97103    typePath  =  resolveToValue ( path . get ( 'id' ) ) ; 
98104    if  ( isUnreachableFlowType ( typePath ) )  { 
99105      return ; 
@@ -104,3 +110,25 @@ function resolveGenericTypeAnnotation(path: NodePath): ?NodePath {
104110
105111  return  typePath ; 
106112} 
113+ 
114+ /** 
115+  * See `supportedUtilityTypes` for which types are supported and 
116+  * https://flow.org/en/docs/types/utilities/ for which types are available. 
117+  */ 
118+ function  isSupportedUtilityType  ( path : NodePath ) : boolean  { 
119+   if  ( types . GenericTypeAnnotation . check ( path . node ) )  { 
120+     const  idPath  =  path . get ( 'id' ) ; 
121+     return  Boolean ( idPath )  && 
122+       supportedUtilityTypes . has ( idPath . node . name ) ; 
123+   } 
124+   return  false ; 
125+ } 
126+ 
127+ /** 
128+  * Unwraps well known utility types. For example: 
129+  * 
130+  *   $ReadOnly<T> => T 
131+  */ 
132+ function  unwrapUtilityType ( path : NodePath ) : ?NodePath  { 
133+   return  path . get ( 'typeParameters' ,  'params' ,  0 ) ; 
134+ } 
0 commit comments