@@ -601,6 +601,10 @@ module.exports = (file, api, options) => {
601
601
// Flow!
602
602
603
603
const flowAnyType = j . anyTypeAnnotation ( ) ;
604
+ const flowFixMeType = j . genericTypeAnnotation (
605
+ j . identifier ( '$FlowFixMe' ) ,
606
+ null
607
+ ) ;
604
608
605
609
const literalToFlowType = node => {
606
610
switch ( typeof node . value ) {
@@ -612,25 +616,25 @@ module.exports = (file, api, options) => {
612
616
return j . booleanLiteralTypeAnnotation ( node . value , node . raw ) ;
613
617
case 'object' : // we already know it's a NullLiteral here
614
618
return j . nullLiteralTypeAnnotation ( ) ;
615
- default :
616
- return flowAnyType ; // meh
619
+ default : // this should never happen
620
+ return flowFixMeType ;
617
621
}
618
622
} ;
619
623
620
624
const propTypeToFlowMapping = {
621
625
// prim types
622
- any : flowAnyType ,
626
+ any : flowAnyType , // this is the only real any
623
627
array : j . genericTypeAnnotation (
624
628
j . identifier ( 'Array' ) ,
625
629
j . typeParameterInstantiation ( [ flowAnyType ] )
626
630
) ,
627
631
bool : j . booleanTypeAnnotation ( ) ,
628
- element : flowAnyType ,
632
+ element : flowAnyType , // flow does the same for `element` type in `propTypes`
629
633
func : j . genericTypeAnnotation (
630
634
j . identifier ( 'Function' ) ,
631
635
null
632
636
) ,
633
- node : flowAnyType ,
637
+ node : flowAnyType , // flow does the same for `node` type in `propTypes`
634
638
number : j . numberTypeAnnotation ( ) ,
635
639
object : j . genericTypeAnnotation (
636
640
j . identifier ( 'Object' ) ,
@@ -664,7 +668,7 @@ module.exports = (file, api, options) => {
664
668
const propTypeToFlowAnnotation = val => {
665
669
let cursor = val ;
666
670
let isOptional = true ;
667
- let typeResult = flowAnyType ;
671
+ let typeResult = flowFixMeType ;
668
672
669
673
if ( // check `.isRequired` first
670
674
cursor . type === 'MemberExpression' &&
@@ -675,68 +679,72 @@ module.exports = (file, api, options) => {
675
679
cursor = cursor . object ;
676
680
}
677
681
678
- if ( cursor . type === 'CallExpression' ) { // type class
679
- const calleeName = cursor . callee . type === 'MemberExpression' ?
680
- cursor . callee . property . name :
681
- cursor . callee . name ;
682
-
683
- const constructor = propTypeToFlowMapping [ calleeName ] ;
684
- if ( ! constructor ) {
685
- typeResult = flowAnyType ;
686
- return [ typeResult , isOptional ] ;
687
- }
688
-
689
- switch ( cursor . callee . property . name ) {
690
- case 'arrayOf' : {
691
- const arg = cursor . arguments [ 0 ] ;
692
- typeResult = constructor (
693
- propTypeToFlowAnnotation ( arg ) [ 0 ]
694
- ) ;
682
+ switch ( cursor . type ) {
683
+ case 'CallExpression' : { // type class
684
+ const calleeName = cursor . callee . type === 'MemberExpression' ?
685
+ cursor . callee . property . name :
686
+ cursor . callee . name ;
687
+
688
+ const constructor = propTypeToFlowMapping [ calleeName ] ;
689
+ if ( ! constructor ) { // unknown type class
690
+ // it's not necessary since `typeResult` defaults to `flowFixMeType`,
691
+ // but it's more explicit this way
692
+ typeResult = flowFixMeType ;
695
693
break ;
696
694
}
697
- case 'instanceOf' : {
698
- const arg = cursor . arguments [ 0 ] ;
699
- if ( arg . type !== 'Identifier' ) {
700
- typeResult = flowAnyType ;
701
- break ;
702
- }
703
695
704
- typeResult = constructor ( arg ) ;
705
- break ;
706
- }
707
- case 'objectOf' : {
708
- const arg = cursor . arguments [ 0 ] ;
709
- const [ valueType , isOptional ] = propTypeToFlowAnnotation ( arg ) ;
710
- typeResult = constructor ( valueType , isOptional ) ;
711
- break ;
712
- }
713
- case 'oneOf' : {
714
- const argList = cursor . arguments [ 0 ] . elements ;
715
- if ( ! argList || ! argList . every ( node => node . type === 'Literal' ) ) {
716
- typeResult = flowAnyType ;
717
- } else {
696
+ switch ( cursor . callee . property . name ) {
697
+ case 'arrayOf' : {
698
+ const arg = cursor . arguments [ 0 ] ;
718
699
typeResult = constructor (
719
- argList . map ( literalToFlowType )
700
+ propTypeToFlowAnnotation ( arg ) [ 0 ]
720
701
) ;
702
+ break ;
721
703
}
722
- break ;
723
- }
724
- case 'oneOfType' : {
725
- const argList = cursor . arguments [ 0 ] . elements ;
726
- if ( ! argList ) {
727
- typeResult = flowAnyType ;
728
- } else {
729
- typeResult = constructor (
730
- argList . map ( arg => propTypeToFlowAnnotation ( arg ) [ 0 ] )
731
- ) ;
704
+ case 'instanceOf' : {
705
+ const arg = cursor . arguments [ 0 ] ;
706
+ if ( arg . type !== 'Identifier' ) {
707
+ typeResult = flowFixMeType ;
708
+ break ;
709
+ }
710
+
711
+ typeResult = constructor ( arg ) ;
712
+ break ;
732
713
}
733
- break ;
734
- }
735
- case 'shape' : {
736
- const rawPropList = cursor . arguments [ 0 ] . properties ;
737
- if ( ! rawPropList ) {
738
- typeResult = flowAnyType ;
739
- } else {
714
+ case 'objectOf' : {
715
+ const arg = cursor . arguments [ 0 ] ;
716
+ const [ valueType , isOptional ] = propTypeToFlowAnnotation ( arg ) ;
717
+ typeResult = constructor ( valueType , isOptional ) ;
718
+ break ;
719
+ }
720
+ case 'oneOf' : {
721
+ const argList = cursor . arguments [ 0 ] . elements ;
722
+ if ( ! argList || ! argList . every ( node => node . type === 'Literal' ) ) {
723
+ typeResult = flowFixMeType ;
724
+ } else {
725
+ typeResult = constructor (
726
+ argList . map ( literalToFlowType )
727
+ ) ;
728
+ }
729
+ break ;
730
+ }
731
+ case 'oneOfType' : {
732
+ const argList = cursor . arguments [ 0 ] . elements ;
733
+ if ( ! argList ) {
734
+ typeResult = flowFixMeType ;
735
+ } else {
736
+ typeResult = constructor (
737
+ argList . map ( arg => propTypeToFlowAnnotation ( arg ) [ 0 ] )
738
+ ) ;
739
+ }
740
+ break ;
741
+ }
742
+ case 'shape' : {
743
+ const rawPropList = cursor . arguments [ 0 ] . properties ;
744
+ if ( ! rawPropList ) {
745
+ typeResult = flowFixMeType ;
746
+ break ;
747
+ }
740
748
const flowPropList = [ ] ;
741
749
rawPropList . forEach ( typeProp => {
742
750
const keyIsLiteral = typeProp . key . type === 'Literal' ;
@@ -745,23 +753,41 @@ module.exports = (file, api, options) => {
745
753
const [ valueType , isOptional ] = propTypeToFlowAnnotation ( typeProp . value ) ;
746
754
flowPropList . push ( j . objectTypeProperty (
747
755
keyIsLiteral ? j . literal ( name ) : j . identifier ( name ) ,
748
- isOptional && valueType !== flowAnyType ?
756
+ // it doesn't make sense to have `?any` or `?$FlowFixMe`
757
+ isOptional && valueType !== flowAnyType && valueType !== flowFixMeType ?
749
758
j . nullableTypeAnnotation ( valueType ) :
750
759
valueType ,
751
760
isOptional
752
761
) ) ;
753
762
} ) ;
754
763
755
764
typeResult = constructor ( flowPropList ) ;
765
+ break ;
766
+ }
767
+ default : {
768
+ break ;
756
769
}
770
+ }
771
+ break ;
772
+ }
773
+ case 'MemberExpression' : { // prim type
774
+ if ( cursor . property . type !== 'Identifier' ) { // unrecognizable
775
+ typeResult = flowFixMeType ;
757
776
break ;
758
777
}
778
+
779
+ const maybeType = propTypeToFlowMapping [ cursor . property . name ] ;
780
+ if ( maybeType ) {
781
+ typeResult = propTypeToFlowMapping [ cursor . property . name ] ;
782
+ } else { // type not found
783
+ typeResult = flowFixMeType ;
784
+ }
785
+
786
+ break ;
787
+ }
788
+ default : { // unrecognizable
789
+ break ;
759
790
}
760
- } else if ( // prim type
761
- cursor . type === 'MemberExpression' &&
762
- cursor . property . type === 'Identifier'
763
- ) {
764
- typeResult = propTypeToFlowMapping [ cursor . property . name ] || flowAnyType ;
765
791
}
766
792
767
793
return [ typeResult , isOptional ] ;
@@ -775,7 +801,7 @@ module.exports = (file, api, options) => {
775
801
}
776
802
777
803
prop . value . properties . forEach ( typeProp => {
778
- if ( ! typeProp . key ) { // SpreadProperty
804
+ if ( ! typeProp . key ) { // stuff like SpreadProperty
779
805
return ;
780
806
}
781
807
@@ -785,7 +811,8 @@ module.exports = (file, api, options) => {
785
811
const [ valueType , isOptional ] = propTypeToFlowAnnotation ( typeProp . value ) ;
786
812
typePropertyList . push ( j . objectTypeProperty (
787
813
keyIsLiteral ? j . literal ( name ) : j . identifier ( name ) ,
788
- isOptional && valueType !== flowAnyType ?
814
+ // it doesn't make sense to have `?any` or `?$FlowFixMe`
815
+ isOptional && valueType !== flowAnyType && valueType !== flowFixMeType ?
789
816
j . nullableTypeAnnotation ( valueType ) :
790
817
valueType ,
791
818
isOptional
0 commit comments