flow-api-translator 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,15 +56,7 @@ function TSDefToFlowDef(originalCode, ast, opts) {
56
56
  interpreter: null,
57
57
  tokens: [],
58
58
  loc: ast.loc,
59
- docblock: {
60
- comment: { ...DUMMY_COMMON,
61
- type: 'Block',
62
- value: ''
63
- },
64
- directives: {
65
- flow: []
66
- }
67
- }
59
+ docblock: null
68
60
  };
69
61
  const [transform, code] = getTransforms(originalCode, opts);
70
62
 
@@ -983,7 +975,9 @@ const getTransforms = (originalCode, opts) => {
983
975
  objectType: base,
984
976
  indexType: constructFlowNode({
985
977
  type: 'StringLiteralTypeAnnotation',
978
+ // $FlowFixMe[incompatible-call]
986
979
  value: name,
980
+ // $FlowFixMe[incompatible-type]
987
981
  raw: `'${name}'`
988
982
  })
989
983
  });
@@ -61,10 +61,7 @@ export function TSDefToFlowDef(
61
61
  interpreter: null,
62
62
  tokens: [],
63
63
  loc: ast.loc,
64
- docblock: {
65
- comment: {...DUMMY_COMMON, type: 'Block', value: ''},
66
- directives: {flow: []},
67
- },
64
+ docblock: null,
68
65
  };
69
66
 
70
67
  const [transform, code] = getTransforms(originalCode, opts);
@@ -1061,7 +1058,9 @@ const getTransforms = (originalCode: string, opts: TranslationOptions) => {
1061
1058
  objectType: base,
1062
1059
  indexType: constructFlowNode<FlowESTree.StringLiteralTypeAnnotation>({
1063
1060
  type: 'StringLiteralTypeAnnotation',
1061
+ // $FlowFixMe[incompatible-call]
1064
1062
  value: name,
1063
+ // $FlowFixMe[incompatible-type]
1065
1064
  raw: `'${name}'`,
1066
1065
  }),
1067
1066
  });
@@ -1731,6 +1731,28 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1731
1731
  return [];
1732
1732
  };
1733
1733
 
1734
+ function assertHasTypeParametersInRange(min, max) {
1735
+ const {
1736
+ typeParameters
1737
+ } = node;
1738
+
1739
+ if (typeParameters == null) {
1740
+ if (min > 0) {
1741
+ throw translationError(node, `Expected between ${min} and ${max} type parameters with \`${fullTypeName}\`, but got none.`);
1742
+ }
1743
+
1744
+ return [];
1745
+ }
1746
+
1747
+ const params = typeParameters.params;
1748
+
1749
+ if (params.length < min || params.length > max) {
1750
+ throw translationError(node, `Expected between ${min} and ${max} type parameters with \`${fullTypeName}\`, but got ${params.length}.`);
1751
+ }
1752
+
1753
+ return typeParameters.params.map(transformTypeAnnotationType);
1754
+ }
1755
+
1734
1756
  switch (fullTypeName) {
1735
1757
  case '$Call':
1736
1758
  case '$ObjMap':
@@ -2054,6 +2076,90 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2054
2076
  }
2055
2077
  };
2056
2078
  }
2079
+
2080
+ case 'StringPrefix':
2081
+ {
2082
+ var _params$;
2083
+
2084
+ // `StringPrefix<foo>` => `foo${string}`
2085
+ // `StringPrefix<foo, T>` => `foo${T}`
2086
+ const params = assertHasTypeParametersInRange(1, 2);
2087
+ const prefix = params[0];
2088
+
2089
+ if (prefix.type !== 'TSLiteralType' || typeof prefix.literal.value !== 'string') {
2090
+ throw translationError(node, 'Expected a string literal for the first type parameter.');
2091
+ }
2092
+
2093
+ const prefixStr = prefix.literal.value;
2094
+ const remainder = (_params$ = params[1]) != null ? _params$ : {
2095
+ type: 'TSStringKeyword',
2096
+ loc: DUMMY_LOC
2097
+ };
2098
+ return {
2099
+ type: 'TSTemplateLiteralType',
2100
+ loc: DUMMY_LOC,
2101
+ quasis: [{
2102
+ type: 'TemplateElement',
2103
+ loc: DUMMY_LOC,
2104
+ value: {
2105
+ raw: prefixStr,
2106
+ cooked: prefixStr
2107
+ },
2108
+ tail: false
2109
+ }, {
2110
+ type: 'TemplateElement',
2111
+ loc: DUMMY_LOC,
2112
+ value: {
2113
+ raw: '',
2114
+ cooked: ''
2115
+ },
2116
+ tail: true
2117
+ }],
2118
+ types: [remainder]
2119
+ };
2120
+ }
2121
+
2122
+ case 'StringSuffix':
2123
+ {
2124
+ var _params$2;
2125
+
2126
+ // `StringSuffix<foo>` => `${string}foo`
2127
+ // `StringSuffix<foo, T>` => `${T}foo`
2128
+ const params = assertHasTypeParametersInRange(1, 2);
2129
+ const suffix = params[0];
2130
+
2131
+ if (suffix.type !== 'TSLiteralType' || typeof suffix.literal.value !== 'string') {
2132
+ throw translationError(node, 'Expected a string literal for the first type parameter.');
2133
+ }
2134
+
2135
+ const suffixStr = suffix.literal.value;
2136
+ const remainder = (_params$2 = params[1]) != null ? _params$2 : {
2137
+ type: 'TSStringKeyword',
2138
+ loc: DUMMY_LOC
2139
+ };
2140
+ return {
2141
+ type: 'TSTemplateLiteralType',
2142
+ loc: DUMMY_LOC,
2143
+ quasis: [{
2144
+ type: 'TemplateElement',
2145
+ loc: DUMMY_LOC,
2146
+ value: {
2147
+ raw: '',
2148
+ cooked: ''
2149
+ },
2150
+ tail: false
2151
+ }, {
2152
+ type: 'TemplateElement',
2153
+ loc: DUMMY_LOC,
2154
+ value: {
2155
+ raw: suffixStr,
2156
+ cooked: suffixStr
2157
+ },
2158
+ tail: true
2159
+ }],
2160
+ types: [remainder]
2161
+ };
2162
+ }
2057
2163
  } // React special conversion:
2058
2164
 
2059
2165
 
@@ -3214,44 +3320,57 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3214
3320
 
3215
3321
  TupleTypeAnnotation(node) {
3216
3322
  const allReadOnly = node.types.length > 0 && node.types.every(element => element.type === 'TupleTypeLabeledElement' && element.variance != null && element.variance.kind === 'plus');
3217
- const tupleAnnot = {
3218
- type: 'TSTupleType',
3219
- loc: DUMMY_LOC,
3220
- elementTypes: node.types.map(element => {
3221
- switch (element.type) {
3222
- case 'TupleTypeLabeledElement':
3223
- if (!allReadOnly && element.variance != null) {
3224
- return unsupportedAnnotation(element, 'tuple type element variance annotations');
3225
- }
3323
+ const elems = node.types.map(element => {
3324
+ switch (element.type) {
3325
+ case 'TupleTypeLabeledElement':
3326
+ if (!allReadOnly && element.variance != null) {
3327
+ return unsupportedAnnotation(element, 'tuple type element variance annotations');
3328
+ }
3226
3329
 
3330
+ return {
3331
+ type: 'TSNamedTupleMember',
3332
+ loc: DUMMY_LOC,
3333
+ label: transform.Identifier(element.label),
3334
+ optional: element.optional,
3335
+ elementType: transformTypeAnnotationType(element.elementType)
3336
+ };
3337
+
3338
+ case 'TupleTypeSpreadElement':
3339
+ {
3340
+ const annot = transformTypeAnnotationType(element.typeAnnotation);
3227
3341
  return {
3228
- type: 'TSNamedTupleMember',
3342
+ type: 'TSRestType',
3229
3343
  loc: DUMMY_LOC,
3230
- label: transform.Identifier(element.label),
3231
- optional: element.optional,
3232
- elementType: transformTypeAnnotationType(element.elementType)
3233
- };
3234
-
3235
- case 'TupleTypeSpreadElement':
3236
- {
3237
- const annot = transformTypeAnnotationType(element.typeAnnotation);
3238
- return {
3239
- type: 'TSRestType',
3344
+ typeAnnotation: element.label != null ? {
3345
+ type: 'TSNamedTupleMember',
3240
3346
  loc: DUMMY_LOC,
3241
- typeAnnotation: element.label != null ? {
3242
- type: 'TSNamedTupleMember',
3243
- loc: DUMMY_LOC,
3244
- label: transform.Identifier(element.label),
3245
- optional: false,
3246
- elementType: annot
3247
- } : annot
3248
- };
3249
- }
3347
+ label: transform.Identifier(element.label),
3348
+ optional: false,
3349
+ elementType: annot
3350
+ } : annot
3351
+ };
3352
+ }
3250
3353
 
3251
- default:
3252
- return transformTypeAnnotationType(element);
3354
+ default:
3355
+ return transformTypeAnnotationType(element);
3356
+ }
3357
+ });
3358
+ const elementTypes = node.inexact ? [...elems, {
3359
+ type: 'TSRestType',
3360
+ loc: DUMMY_LOC,
3361
+ typeAnnotation: {
3362
+ type: 'TSArrayType',
3363
+ loc: DUMMY_LOC,
3364
+ elementType: {
3365
+ type: 'TSUnknownKeyword',
3366
+ loc: DUMMY_LOC
3253
3367
  }
3254
- })
3368
+ }
3369
+ }] : elems;
3370
+ const tupleAnnot = {
3371
+ type: 'TSTupleType',
3372
+ loc: DUMMY_LOC,
3373
+ elementTypes
3255
3374
  };
3256
3375
  return allReadOnly ? {
3257
3376
  type: 'TSTypeOperator',
@@ -1915,6 +1915,31 @@ const getTransforms = (
1915
1915
  return [];
1916
1916
  };
1917
1917
 
1918
+ function assertHasTypeParametersInRange(
1919
+ min: number,
1920
+ max: number,
1921
+ ): $ReadOnlyArray<TSESTree.TypeNode> {
1922
+ const {typeParameters} = node;
1923
+ if (typeParameters == null) {
1924
+ if (min > 0) {
1925
+ throw translationError(
1926
+ node,
1927
+ `Expected between ${min} and ${max} type parameters with \`${fullTypeName}\`, but got none.`,
1928
+ );
1929
+ }
1930
+ return [];
1931
+ }
1932
+ const params = typeParameters.params;
1933
+ if (params.length < min || params.length > max) {
1934
+ throw translationError(
1935
+ node,
1936
+ `Expected between ${min} and ${max} type parameters with \`${fullTypeName}\`, but got ${params.length}.`,
1937
+ );
1938
+ }
1939
+
1940
+ return typeParameters.params.map(transformTypeAnnotationType);
1941
+ }
1942
+
1918
1943
  switch (fullTypeName) {
1919
1944
  case '$Call':
1920
1945
  case '$ObjMap':
@@ -2242,6 +2267,100 @@ const getTransforms = (
2242
2267
  },
2243
2268
  };
2244
2269
  }
2270
+
2271
+ case 'StringPrefix': {
2272
+ // `StringPrefix<foo>` => `foo${string}`
2273
+ // `StringPrefix<foo, T>` => `foo${T}`
2274
+ const params = assertHasTypeParametersInRange(1, 2);
2275
+ const prefix = params[0];
2276
+ if (
2277
+ prefix.type !== 'TSLiteralType' ||
2278
+ typeof prefix.literal.value !== 'string'
2279
+ ) {
2280
+ throw translationError(
2281
+ node,
2282
+ 'Expected a string literal for the first type parameter.',
2283
+ );
2284
+ }
2285
+ const prefixStr = prefix.literal.value;
2286
+ const remainder = params[1] ?? {
2287
+ type: 'TSStringKeyword',
2288
+ loc: DUMMY_LOC,
2289
+ };
2290
+
2291
+ return {
2292
+ type: 'TSTemplateLiteralType',
2293
+ loc: DUMMY_LOC,
2294
+ quasis: [
2295
+ {
2296
+ type: 'TemplateElement',
2297
+ loc: DUMMY_LOC,
2298
+ value: {
2299
+ raw: prefixStr,
2300
+ cooked: prefixStr,
2301
+ },
2302
+ tail: false,
2303
+ },
2304
+ {
2305
+ type: 'TemplateElement',
2306
+ loc: DUMMY_LOC,
2307
+ value: {
2308
+ raw: '',
2309
+ cooked: '',
2310
+ },
2311
+ tail: true,
2312
+ },
2313
+ ],
2314
+ types: [remainder],
2315
+ };
2316
+ }
2317
+
2318
+ case 'StringSuffix': {
2319
+ // `StringSuffix<foo>` => `${string}foo`
2320
+ // `StringSuffix<foo, T>` => `${T}foo`
2321
+ const params = assertHasTypeParametersInRange(1, 2);
2322
+ const suffix = params[0];
2323
+ if (
2324
+ suffix.type !== 'TSLiteralType' ||
2325
+ typeof suffix.literal.value !== 'string'
2326
+ ) {
2327
+ throw translationError(
2328
+ node,
2329
+ 'Expected a string literal for the first type parameter.',
2330
+ );
2331
+ }
2332
+ const suffixStr = suffix.literal.value;
2333
+ const remainder = params[1] ?? {
2334
+ type: 'TSStringKeyword',
2335
+ loc: DUMMY_LOC,
2336
+ };
2337
+
2338
+ return {
2339
+ type: 'TSTemplateLiteralType',
2340
+ loc: DUMMY_LOC,
2341
+ quasis: [
2342
+ {
2343
+ type: 'TemplateElement',
2344
+ loc: DUMMY_LOC,
2345
+ value: {
2346
+ raw: '',
2347
+ cooked: '',
2348
+ },
2349
+ tail: false,
2350
+ },
2351
+ {
2352
+ type: 'TemplateElement',
2353
+ loc: DUMMY_LOC,
2354
+ value: {
2355
+ raw: suffixStr,
2356
+ cooked: suffixStr,
2357
+ },
2358
+ tail: true,
2359
+ },
2360
+ ],
2361
+ types: [remainder],
2362
+ };
2363
+ }
2245
2364
  }
2246
2365
 
2247
2366
  // React special conversion:
@@ -3501,46 +3620,66 @@ const getTransforms = (
3501
3620
  element.variance != null &&
3502
3621
  element.variance.kind === 'plus',
3503
3622
  );
3623
+ const elems = node.types.map(element => {
3624
+ switch (element.type) {
3625
+ case 'TupleTypeLabeledElement':
3626
+ if (!allReadOnly && element.variance != null) {
3627
+ return unsupportedAnnotation(
3628
+ element,
3629
+ 'tuple type element variance annotations',
3630
+ );
3631
+ }
3632
+ return {
3633
+ type: 'TSNamedTupleMember',
3634
+ loc: DUMMY_LOC,
3635
+ label: transform.Identifier(element.label),
3636
+ optional: element.optional,
3637
+ elementType: transformTypeAnnotationType(element.elementType),
3638
+ };
3639
+ case 'TupleTypeSpreadElement': {
3640
+ const annot = transformTypeAnnotationType(element.typeAnnotation);
3641
+ return {
3642
+ type: 'TSRestType',
3643
+ loc: DUMMY_LOC,
3644
+ typeAnnotation:
3645
+ element.label != null
3646
+ ? {
3647
+ type: 'TSNamedTupleMember',
3648
+ loc: DUMMY_LOC,
3649
+ label: transform.Identifier(element.label),
3650
+ optional: false,
3651
+ elementType: annot,
3652
+ }
3653
+ : annot,
3654
+ };
3655
+ }
3656
+ default:
3657
+ return transformTypeAnnotationType(element);
3658
+ }
3659
+ });
3660
+
3661
+ const elementTypes = node.inexact
3662
+ ? [
3663
+ ...elems,
3664
+ {
3665
+ type: 'TSRestType',
3666
+ loc: DUMMY_LOC,
3667
+ typeAnnotation: {
3668
+ type: 'TSArrayType',
3669
+ loc: DUMMY_LOC,
3670
+ elementType: {
3671
+ type: 'TSUnknownKeyword',
3672
+ loc: DUMMY_LOC,
3673
+ },
3674
+ },
3675
+ },
3676
+ ]
3677
+ : elems;
3678
+
3504
3679
  const tupleAnnot: TSESTree.TSTupleType = {
3505
3680
  type: 'TSTupleType',
3506
3681
  loc: DUMMY_LOC,
3507
- elementTypes: node.types.map(element => {
3508
- switch (element.type) {
3509
- case 'TupleTypeLabeledElement':
3510
- if (!allReadOnly && element.variance != null) {
3511
- return unsupportedAnnotation(
3512
- element,
3513
- 'tuple type element variance annotations',
3514
- );
3515
- }
3516
- return {
3517
- type: 'TSNamedTupleMember',
3518
- loc: DUMMY_LOC,
3519
- label: transform.Identifier(element.label),
3520
- optional: element.optional,
3521
- elementType: transformTypeAnnotationType(element.elementType),
3522
- };
3523
- case 'TupleTypeSpreadElement': {
3524
- const annot = transformTypeAnnotationType(element.typeAnnotation);
3525
- return {
3526
- type: 'TSRestType',
3527
- loc: DUMMY_LOC,
3528
- typeAnnotation:
3529
- element.label != null
3530
- ? {
3531
- type: 'TSNamedTupleMember',
3532
- loc: DUMMY_LOC,
3533
- label: transform.Identifier(element.label),
3534
- optional: false,
3535
- elementType: annot,
3536
- }
3537
- : annot,
3538
- };
3539
- }
3540
- default:
3541
- return transformTypeAnnotationType(element);
3542
- }
3543
- }),
3682
+ elementTypes,
3544
3683
  };
3545
3684
  return allReadOnly
3546
3685
  ? {
@@ -751,23 +751,84 @@ function convertClassDeclaration(class_, context) {
751
751
  }), [...typeParamsDeps, ...implementsDeps, ...superClassDeps, ...bodyDeps]];
752
752
  }
753
753
 
754
- function convertSuperClass(superClass, superTypeParameters, context) {
755
- if (superClass == null) {
756
- return EMPTY_TRANSLATION_RESULT;
754
+ function convertExpressionToIdentifier(node, context) {
755
+ if (node.type === 'Identifier') {
756
+ return _hermesTransform.t.Identifier({
757
+ name: node.name
758
+ });
757
759
  }
758
760
 
759
- if (superClass.type !== 'Identifier') {
760
- throw (0, _ErrorUtils.translationError)(superClass, `SuperClass: Non identifier super type of "${superClass.type}" not supported`, context);
761
+ if (node.type === 'MemberExpression') {
762
+ const {
763
+ property,
764
+ object
765
+ } = node;
766
+
767
+ if (property.type === 'Identifier' && object.type !== 'Super') {
768
+ return _hermesTransform.t.QualifiedTypeIdentifier({
769
+ qualification: convertExpressionToIdentifier(object, context),
770
+ id: _hermesTransform.t.Identifier({
771
+ name: property.name
772
+ })
773
+ });
774
+ }
761
775
  }
762
776
 
777
+ throw (0, _ErrorUtils.translationError)(node, `Expected ${node.type} to be an Identifier or Member with Identifier property, non-Super object.`, context);
778
+ }
779
+
780
+ function convertSuperClassHelper(detachedId, nodeForDependencies, superTypeParameters, context) {
763
781
  const [resultTypeParams, typeParamsDeps] = convertTypeParameterInstantiationOrNull(superTypeParameters, context);
764
- const superDeps = (0, _FlowAnalyze.analyzeTypeDependencies)(superClass, context);
782
+ const superDeps = (0, _FlowAnalyze.analyzeTypeDependencies)(nodeForDependencies, context);
765
783
  return [_hermesTransform.t.InterfaceExtends({
766
- id: (0, _hermesTransform.asDetachedNode)(superClass),
784
+ id: detachedId,
767
785
  typeParameters: resultTypeParams
768
786
  }), [...typeParamsDeps, ...superDeps]];
769
787
  }
770
788
 
789
+ function convertSuperClass(superClass, superTypeParameters, context) {
790
+ if (superClass == null) {
791
+ return EMPTY_TRANSLATION_RESULT;
792
+ }
793
+
794
+ switch (superClass.type) {
795
+ case 'Identifier':
796
+ {
797
+ return convertSuperClassHelper((0, _hermesTransform.asDetachedNode)(superClass), superClass, superTypeParameters, context);
798
+ }
799
+
800
+ case 'MemberExpression':
801
+ {
802
+ return convertSuperClassHelper(convertExpressionToIdentifier(superClass, context), superClass, superTypeParameters, context);
803
+ }
804
+
805
+ case 'TypeCastExpression':
806
+ case 'AsExpression':
807
+ {
808
+ const typeAnnotation = superClass.type === 'TypeCastExpression' ? superClass.typeAnnotation.typeAnnotation : superClass.typeAnnotation;
809
+
810
+ if (typeAnnotation.type === 'GenericTypeAnnotation') {
811
+ return convertSuperClassHelper((0, _hermesTransform.asDetachedNode)(typeAnnotation.id), typeAnnotation, superTypeParameters, context);
812
+ }
813
+
814
+ if (typeAnnotation.type === 'TypeofTypeAnnotation') {
815
+ const typeofArg = typeAnnotation.argument;
816
+
817
+ if (typeofArg.type === 'Identifier') {
818
+ return convertSuperClassHelper((0, _hermesTransform.asDetachedNode)(typeofArg), typeofArg, typeAnnotation.typeArguments, context);
819
+ }
820
+ }
821
+
822
+ throw (0, _ErrorUtils.translationError)(superClass, `SuperClass: Typecast super type of "${typeAnnotation.type}" not supported`, context);
823
+ }
824
+
825
+ default:
826
+ {
827
+ throw (0, _ErrorUtils.translationError)(superClass, `SuperClass: Non identifier super type of "${superClass.type}" not supported`, context);
828
+ }
829
+ }
830
+ }
831
+
771
832
  function convertClassBody(body, context) {
772
833
  const [resultProperties, deps] = convertArray(body.body, member => convertClassMember(member, context));
773
834
  return [_hermesTransform.t.ObjectTypeAnnotation({
@@ -49,6 +49,7 @@ import type {
49
49
  ObjectTypeAnnotation,
50
50
  ObjectTypeProperty,
51
51
  OpaqueType,
52
+ QualifiedTypeIdentifier,
52
53
  Program,
53
54
  RestElement,
54
55
  Statement,
@@ -977,34 +978,120 @@ function convertClassDeclaration(
977
978
  ];
978
979
  }
979
980
 
980
- function convertSuperClass(
981
- superClass: ?Expression,
982
- superTypeParameters: ?TypeParameterInstantiation,
981
+ function convertExpressionToIdentifier(
982
+ node: Expression,
983
983
  context: TranslationContext,
984
- ): TranslatedResultOrNull<InterfaceExtends> {
985
- if (superClass == null) {
986
- return EMPTY_TRANSLATION_RESULT;
984
+ ): DetachedNode<Identifier> | DetachedNode<QualifiedTypeIdentifier> {
985
+ if (node.type === 'Identifier') {
986
+ return t.Identifier({name: node.name});
987
987
  }
988
988
 
989
- if (superClass.type !== 'Identifier') {
990
- throw translationError(
991
- superClass,
992
- `SuperClass: Non identifier super type of "${superClass.type}" not supported`,
993
- context,
994
- );
989
+ if (node.type === 'MemberExpression') {
990
+ const {property, object} = node;
991
+ if (property.type === 'Identifier' && object.type !== 'Super') {
992
+ return t.QualifiedTypeIdentifier({
993
+ qualification: convertExpressionToIdentifier(object, context),
994
+ id: t.Identifier({name: property.name}),
995
+ });
996
+ }
995
997
  }
998
+
999
+ throw translationError(
1000
+ node,
1001
+ `Expected ${node.type} to be an Identifier or Member with Identifier property, non-Super object.`,
1002
+ context,
1003
+ );
1004
+ }
1005
+
1006
+ function convertSuperClassHelper(
1007
+ detachedId: DetachedNode<Identifier | QualifiedTypeIdentifier>,
1008
+ nodeForDependencies: ESNode,
1009
+ superTypeParameters: ?TypeParameterInstantiation,
1010
+ context: TranslationContext,
1011
+ ): TranslatedResultOrNull<InterfaceExtends> {
996
1012
  const [resultTypeParams, typeParamsDeps] =
997
1013
  convertTypeParameterInstantiationOrNull(superTypeParameters, context);
998
- const superDeps = analyzeTypeDependencies(superClass, context);
1014
+ const superDeps = analyzeTypeDependencies(nodeForDependencies, context);
999
1015
  return [
1000
1016
  t.InterfaceExtends({
1001
- id: asDetachedNode(superClass),
1017
+ id: detachedId,
1002
1018
  typeParameters: resultTypeParams,
1003
1019
  }),
1004
1020
  [...typeParamsDeps, ...superDeps],
1005
1021
  ];
1006
1022
  }
1007
1023
 
1024
+ function convertSuperClass(
1025
+ superClass: ?Expression,
1026
+ superTypeParameters: ?TypeParameterInstantiation,
1027
+ context: TranslationContext,
1028
+ ): TranslatedResultOrNull<InterfaceExtends> {
1029
+ if (superClass == null) {
1030
+ return EMPTY_TRANSLATION_RESULT;
1031
+ }
1032
+
1033
+ switch (superClass.type) {
1034
+ case 'Identifier': {
1035
+ return convertSuperClassHelper(
1036
+ asDetachedNode(superClass),
1037
+ superClass,
1038
+ superTypeParameters,
1039
+ context,
1040
+ );
1041
+ }
1042
+ case 'MemberExpression': {
1043
+ return convertSuperClassHelper(
1044
+ convertExpressionToIdentifier(superClass, context),
1045
+ superClass,
1046
+ superTypeParameters,
1047
+ context,
1048
+ );
1049
+ }
1050
+ case 'TypeCastExpression':
1051
+ case 'AsExpression': {
1052
+ const typeAnnotation =
1053
+ superClass.type === 'TypeCastExpression'
1054
+ ? superClass.typeAnnotation.typeAnnotation
1055
+ : superClass.typeAnnotation;
1056
+
1057
+ if (typeAnnotation.type === 'GenericTypeAnnotation') {
1058
+ return convertSuperClassHelper(
1059
+ asDetachedNode(typeAnnotation.id),
1060
+ typeAnnotation,
1061
+ superTypeParameters,
1062
+ context,
1063
+ );
1064
+ }
1065
+
1066
+ if (typeAnnotation.type === 'TypeofTypeAnnotation') {
1067
+ const typeofArg = typeAnnotation.argument;
1068
+
1069
+ if (typeofArg.type === 'Identifier') {
1070
+ return convertSuperClassHelper(
1071
+ asDetachedNode(typeofArg),
1072
+ typeofArg,
1073
+ typeAnnotation.typeArguments,
1074
+ context,
1075
+ );
1076
+ }
1077
+ }
1078
+
1079
+ throw translationError(
1080
+ superClass,
1081
+ `SuperClass: Typecast super type of "${typeAnnotation.type}" not supported`,
1082
+ context,
1083
+ );
1084
+ }
1085
+ default: {
1086
+ throw translationError(
1087
+ superClass,
1088
+ `SuperClass: Non identifier super type of "${superClass.type}" not supported`,
1089
+ context,
1090
+ );
1091
+ }
1092
+ }
1093
+ }
1094
+
1008
1095
  function convertClassBody(
1009
1096
  body: ClassBody,
1010
1097
  context: TranslationContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-api-translator",
3
- "version": "0.22.0",
3
+ "version": "0.23.1",
4
4
  "description": "Toolkit for creating Flow and TypeScript compatible libraries from Flow source code.",
5
5
  "main": "dist/index.js",
6
6
  "license": "MIT",
@@ -13,10 +13,10 @@
13
13
  "@typescript-eslint/parser": "7.2.0",
14
14
  "@typescript-eslint/visitor-keys": "7.2.0",
15
15
  "flow-enums-runtime": "^0.0.6",
16
- "hermes-eslint": "0.22.0",
17
- "hermes-estree": "0.22.0",
18
- "hermes-parser": "0.22.0",
19
- "hermes-transform": "0.22.0",
16
+ "hermes-eslint": "0.23.1",
17
+ "hermes-estree": "0.23.1",
18
+ "hermes-parser": "0.23.1",
19
+ "hermes-transform": "0.23.1",
20
20
  "typescript": "5.3.2"
21
21
  },
22
22
  "peerDependencies": {