flow-api-translator 0.26.0 → 0.27.0

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.
@@ -879,14 +879,45 @@ const getTransforms = (originalCode, scopeManager, opts) => {
879
879
  cloneJSDocCommentsToNewNode(member, newNode);
880
880
  classMembers.push(newNode);
881
881
  } else {
882
- var _member$computed, _member$static;
882
+ var _member$static;
883
+
884
+ const [key, computed] = (() => {
885
+ const _key = member.key;
886
+
887
+ if (_key.type === 'Identifier' && _key.name.startsWith('@@')) {
888
+ const name = _key.name.slice(2);
889
+
890
+ if (['iterator', 'asyncIterator'].includes(name)) {
891
+ return [{
892
+ type: 'MemberExpression',
893
+ computed: false,
894
+ object: {
895
+ type: 'Identifier',
896
+ name: 'Symbol',
897
+ optional: false,
898
+ loc: DUMMY_LOC
899
+ },
900
+ optional: false,
901
+ property: {
902
+ type: 'Identifier',
903
+ name,
904
+ optional: false,
905
+ loc: DUMMY_LOC
906
+ },
907
+ loc: DUMMY_LOC
908
+ }, true];
909
+ }
910
+ }
911
+
912
+ return [member.key, member.computed];
913
+ })();
883
914
 
884
915
  const newNode = {
885
916
  type: 'MethodDefinition',
886
917
  loc: DUMMY_LOC,
887
918
  accessibility: member.accessibility,
888
- computed: (_member$computed = member.computed) != null ? _member$computed : false,
889
- key: member.key,
919
+ computed: computed != null ? computed : false,
920
+ key,
890
921
  kind: member.kind,
891
922
  optional: member.optional,
892
923
  override: false,
@@ -914,13 +945,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
914
945
 
915
946
  case 'TSPropertySignature':
916
947
  {
917
- var _member$computed2, _member$static2;
948
+ var _member$computed, _member$static2;
918
949
 
919
950
  const newNode = {
920
951
  type: 'PropertyDefinition',
921
952
  loc: DUMMY_LOC,
922
953
  accessibility: member.accessibility,
923
- computed: (_member$computed2 = member.computed) != null ? _member$computed2 : false,
954
+ computed: (_member$computed = member.computed) != null ? _member$computed : false,
924
955
  declare: false,
925
956
  key: member.key,
926
957
  optional: member.optional,
@@ -974,8 +1005,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
974
1005
  declare: true,
975
1006
  id: transform.Identifier(node.id, false),
976
1007
  implements: node.implements == null ? undefined : node.implements.map(transform.ClassImplements),
977
- superClass: superClass == null ? null : // Bug: superclass.id can be qualified
978
- transform.Identifier(superClass.id, false),
1008
+ superClass: superClass == null ? null : superClass.id.type === 'QualifiedTypeIdentifier' ? transform.QualifiedTypeIdentifier(superClass.id) : transform.Identifier(superClass.id, false),
979
1009
  superTypeParameters: (superClass == null ? void 0 : superClass.typeParameters) == null ? undefined : transform.TypeParameterInstantiation(superClass.typeParameters),
980
1010
  typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters) // TODO - mixins??
981
1011
 
@@ -1117,6 +1147,37 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1117
1147
 
1118
1148
  }
1119
1149
 
1150
+ case 'TypeofTypeAnnotation':
1151
+ {
1152
+ if (declaration.type === 'TypeofTypeAnnotation' && declaration.argument.type === 'Identifier') {
1153
+ const name = declaration.argument.name;
1154
+ const exportedVar = topScope.set.get(name);
1155
+
1156
+ if (exportedVar != null && exportedVar.defs.length === 1) {
1157
+ const def = exportedVar.defs[0];
1158
+
1159
+ switch (def.type) {
1160
+ case 'ClassName':
1161
+ {
1162
+ return {
1163
+ type: 'ExportDefaultDeclaration',
1164
+ declaration: {
1165
+ type: 'Identifier',
1166
+ decorators: [],
1167
+ name,
1168
+ optional: false,
1169
+ loc: DUMMY_LOC
1170
+ },
1171
+ exportKind: 'value',
1172
+ loc: DUMMY_LOC
1173
+ };
1174
+ }
1175
+ }
1176
+ }
1177
+ } // intentional fallthrough to the "default" handling
1178
+
1179
+ }
1180
+
1120
1181
  default:
1121
1182
  {
1122
1183
  /*
@@ -1152,6 +1213,28 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1152
1213
  }],
1153
1214
  declare: true,
1154
1215
  kind: 'const'
1216
+ }, {
1217
+ type: 'TSTypeAliasDeclaration',
1218
+ declare: true,
1219
+ id: {
1220
+ type: 'Identifier',
1221
+ decorators: [],
1222
+ name: SPECIFIER,
1223
+ optional: false,
1224
+ loc: DUMMY_LOC
1225
+ },
1226
+ typeAnnotation: {
1227
+ type: 'TSTypeQuery',
1228
+ exprName: {
1229
+ type: 'Identifier',
1230
+ decorators: [],
1231
+ name: SPECIFIER,
1232
+ optional: false,
1233
+ loc: DUMMY_LOC
1234
+ },
1235
+ loc: DUMMY_LOC
1236
+ },
1237
+ loc: DUMMY_LOC
1155
1238
  }, {
1156
1239
  type: 'ExportDefaultDeclaration',
1157
1240
  loc: DUMMY_LOC,
@@ -1243,19 +1326,72 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1243
1326
  }
1244
1327
  })();
1245
1328
 
1246
- return declarations.map(({
1329
+ const mappedDeclarations = declarations.map(({
1247
1330
  declaration,
1248
1331
  exportKind
1249
- }) => ({
1250
- type: 'ExportNamedDeclaration',
1251
- loc: DUMMY_LOC,
1252
- // flow does not currently support assertions
1253
- assertions: [],
1254
- declaration,
1255
- exportKind,
1256
- source: null,
1257
- specifiers: []
1258
- }));
1332
+ }) => {
1333
+ if (declaration.type === 'VariableDeclaration' && declaration.declarations.length === 1) {
1334
+ const ident = declaration.declarations[0].id;
1335
+
1336
+ if (ident.type === 'Identifier') {
1337
+ const name = ident.name;
1338
+ return [{
1339
+ type: 'ExportNamedDeclaration',
1340
+ loc: DUMMY_LOC,
1341
+ // flow does not currently support assertions
1342
+ assertions: [],
1343
+ declaration,
1344
+ exportKind,
1345
+ source: null,
1346
+ specifiers: []
1347
+ }, {
1348
+ type: 'ExportNamedDeclaration',
1349
+ declaration: {
1350
+ type: 'TSTypeAliasDeclaration',
1351
+ declare: true,
1352
+ id: {
1353
+ type: 'Identifier',
1354
+ decorators: [],
1355
+ name,
1356
+ optional: false,
1357
+ loc: DUMMY_LOC
1358
+ },
1359
+ typeAnnotation: {
1360
+ type: 'TSTypeQuery',
1361
+ exprName: {
1362
+ type: 'Identifier',
1363
+ decorators: [],
1364
+ name,
1365
+ optional: false,
1366
+ loc: DUMMY_LOC
1367
+ },
1368
+ loc: DUMMY_LOC
1369
+ },
1370
+ loc: DUMMY_LOC
1371
+ },
1372
+ source: null,
1373
+ loc: DUMMY_LOC,
1374
+ specifiers: [],
1375
+ exportKind: 'type',
1376
+ // flow does not currently support assertions
1377
+ assertions: []
1378
+ }];
1379
+ }
1380
+ }
1381
+
1382
+ const exportNamedDeclaration = {
1383
+ type: 'ExportNamedDeclaration',
1384
+ loc: DUMMY_LOC,
1385
+ // flow does not currently support assertions
1386
+ assertions: [],
1387
+ declaration,
1388
+ exportKind,
1389
+ source: null,
1390
+ specifiers: []
1391
+ };
1392
+ return exportNamedDeclaration;
1393
+ });
1394
+ return mappedDeclarations.flat();
1259
1395
  } else {
1260
1396
  return {
1261
1397
  type: 'ExportNamedDeclaration',
@@ -1472,6 +1608,45 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1472
1608
  // TS doesn't currently have nominal types - https://github.com/Microsoft/Typescript/issues/202
1473
1609
  // TODO - we could simulate this in a variety of ways
1474
1610
  // Examples - https://basarat.gitbook.io/typescript/main-1/nominaltyping
1611
+ if (node.supertype == null && node.typeParameters == null) {
1612
+ const name = `__${node.id.name}__`;
1613
+ return {
1614
+ type: 'TSTypeAliasDeclaration',
1615
+ loc: DUMMY_LOC,
1616
+ declare: true,
1617
+ id: transform.Identifier(node.id, false),
1618
+ typeAnnotation: {
1619
+ type: 'TSIntersectionType',
1620
+ types: [{
1621
+ type: 'TSSymbolKeyword',
1622
+ loc: DUMMY_LOC
1623
+ }, {
1624
+ type: 'TSTypeLiteral',
1625
+ loc: DUMMY_LOC,
1626
+ members: [{
1627
+ type: 'TSPropertySignature',
1628
+ computed: false,
1629
+ loc: DUMMY_LOC,
1630
+ key: {
1631
+ type: 'Identifier',
1632
+ name: name,
1633
+ loc: DUMMY_LOC
1634
+ },
1635
+ typeAnnotation: {
1636
+ type: 'TSTypeAnnotation',
1637
+ loc: DUMMY_LOC,
1638
+ typeAnnotation: {
1639
+ type: 'TSStringKeyword',
1640
+ loc: DUMMY_LOC
1641
+ }
1642
+ }
1643
+ }]
1644
+ }],
1645
+ loc: DUMMY_LOC
1646
+ }
1647
+ };
1648
+ }
1649
+
1475
1650
  return {
1476
1651
  type: 'TSTypeAliasDeclaration',
1477
1652
  loc: DUMMY_LOC,
@@ -1782,6 +1957,25 @@ const getTransforms = (originalCode, scopeManager, opts) => {
1782
1957
  return unsupportedAnnotation(node, fullTypeName);
1783
1958
  }
1784
1959
 
1960
+ case '$ArrayLike':
1961
+ {
1962
+ // `$ArrayLike<T>` => `ArrayLike<T>`
1963
+ return {
1964
+ type: 'TSTypeReference',
1965
+ loc: DUMMY_LOC,
1966
+ typeName: {
1967
+ type: 'Identifier',
1968
+ loc: DUMMY_LOC,
1969
+ name: 'ArrayLike'
1970
+ },
1971
+ typeParameters: {
1972
+ type: 'TSTypeParameterInstantiation',
1973
+ loc: DUMMY_LOC,
1974
+ params: assertHasExactlyNTypeParameters(1)
1975
+ }
1976
+ };
1977
+ }
1978
+
1785
1979
  case '$Diff':
1786
1980
  case '$Rest':
1787
1981
  {
@@ -2393,7 +2587,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2393
2587
  }
2394
2588
  }
2395
2589
  };
2396
- // React.MixedElement -> JSX.Element
2590
+ // React.MixedElement -> React.JSX.Element
2397
2591
 
2398
2592
  case 'React$MixedElement':
2399
2593
  case 'React.MixedElement':
@@ -2406,9 +2600,18 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2406
2600
  type: 'TSQualifiedName',
2407
2601
  loc: DUMMY_LOC,
2408
2602
  left: {
2409
- type: 'Identifier',
2603
+ type: 'TSQualifiedName',
2410
2604
  loc: DUMMY_LOC,
2411
- name: 'JSX'
2605
+ left: {
2606
+ type: 'Identifier',
2607
+ loc: DUMMY_LOC,
2608
+ name: 'React'
2609
+ },
2610
+ right: {
2611
+ type: 'Identifier',
2612
+ loc: DUMMY_LOC,
2613
+ name: 'JSX'
2614
+ }
2412
2615
  },
2413
2616
  right: {
2414
2617
  type: 'Identifier',
@@ -2547,8 +2750,8 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2547
2750
  }
2548
2751
  };
2549
2752
  }
2550
- // React.ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2551
- // React$ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2753
+ // React.ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2754
+ // React$ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2552
2755
 
2553
2756
  case 'React.ElementConfig':
2554
2757
  case 'React$ElementConfig':
@@ -2561,9 +2764,18 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2561
2764
  type: 'TSQualifiedName',
2562
2765
  loc: DUMMY_LOC,
2563
2766
  left: {
2564
- type: 'Identifier',
2767
+ type: 'TSQualifiedName',
2565
2768
  loc: DUMMY_LOC,
2566
- name: 'JSX'
2769
+ left: {
2770
+ type: 'Identifier',
2771
+ loc: DUMMY_LOC,
2772
+ name: 'React'
2773
+ },
2774
+ right: {
2775
+ type: 'Identifier',
2776
+ loc: DUMMY_LOC,
2777
+ name: 'JSX'
2778
+ }
2567
2779
  },
2568
2780
  right: {
2569
2781
  type: 'Identifier',
@@ -2738,8 +2950,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
2738
2950
  return {
2739
2951
  type: 'TSInterfaceHeritage',
2740
2952
  loc: DUMMY_LOC,
2741
- // Bug: node.id can be qualified
2742
- expression: transform.Identifier(node.id, false),
2953
+ expression: node.id.type === 'QualifiedTypeIdentifier' ? transform.QualifiedTypeIdentifier(node.id) : transform.Identifier(node.id, false),
2743
2954
  typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterInstantiation(node.typeParameters)
2744
2955
  };
2745
2956
  },
@@ -3024,7 +3235,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3024
3235
 
3025
3236
  const spreadType = transformTypeAnnotationType(property.argument);
3026
3237
 
3027
- if (spreadType.type !== 'TSTypeReference') {
3238
+ if (spreadType.type !== 'TSTypeReference' && spreadType.type !== 'TSTypeQuery') {
3028
3239
  return unsupportedAnnotation(property, 'object types with complex spreads');
3029
3240
  }
3030
3241
 
@@ -3100,7 +3311,40 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3100
3311
  },
3101
3312
 
3102
3313
  ObjectTypeIndexer(node) {
3103
- var _node$variance;
3314
+ var _node$variance2;
3315
+
3316
+ if (node.key.type === 'GenericTypeAnnotation') {
3317
+ var _node$variance;
3318
+
3319
+ const ident = node.key.id.type === 'Identifier' ? node.key.id : node.key.id.id;
3320
+ return {
3321
+ type: 'TSPropertySignature',
3322
+ computed: true,
3323
+ loc: DUMMY_LOC,
3324
+ key: {
3325
+ type: 'BinaryExpression',
3326
+ operator: 'in',
3327
+ loc: DUMMY_LOC,
3328
+ left: {
3329
+ type: 'Identifier',
3330
+ name: node.id == null ? '$$Key$$' : node.id.name,
3331
+ loc: DUMMY_LOC
3332
+ },
3333
+ right: {
3334
+ type: 'Identifier',
3335
+ name: ident.name,
3336
+ loc: DUMMY_LOC
3337
+ }
3338
+ },
3339
+ readonly: ((_node$variance = node.variance) == null ? void 0 : _node$variance.kind) === 'plus',
3340
+ static: node.static,
3341
+ typeAnnotation: {
3342
+ type: 'TSTypeAnnotation',
3343
+ loc: DUMMY_LOC,
3344
+ typeAnnotation: transformTypeAnnotationType(node.value)
3345
+ }
3346
+ };
3347
+ }
3104
3348
 
3105
3349
  return {
3106
3350
  type: 'TSIndexSignature',
@@ -3115,7 +3359,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3115
3359
  typeAnnotation: transformTypeAnnotationType(node.key)
3116
3360
  }
3117
3361
  }],
3118
- readonly: ((_node$variance = node.variance) == null ? void 0 : _node$variance.kind) === 'plus',
3362
+ readonly: ((_node$variance2 = node.variance) == null ? void 0 : _node$variance2.kind) === 'plus',
3119
3363
  static: node.static,
3120
3364
  typeAnnotation: {
3121
3365
  type: 'TSTypeAnnotation',
@@ -3126,7 +3370,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3126
3370
  },
3127
3371
 
3128
3372
  ObjectTypeProperty(node) {
3129
- var _node$variance2;
3373
+ var _node$variance3;
3130
3374
 
3131
3375
  const key = node.key.type === 'Identifier' ? transform.Identifier(node.key) : transform.StringLiteral(node.key);
3132
3376
 
@@ -3174,7 +3418,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
3174
3418
  computed: false,
3175
3419
  key,
3176
3420
  optional: node.optional,
3177
- readonly: ((_node$variance2 = node.variance) == null ? void 0 : _node$variance2.kind) === 'plus',
3421
+ readonly: ((_node$variance3 = node.variance) == null ? void 0 : _node$variance3.kind) === 'plus',
3178
3422
  static: node.static,
3179
3423
  typeAnnotation: {
3180
3424
  type: 'TSTypeAnnotation',
@@ -928,12 +928,44 @@ const getTransforms = (
928
928
  cloneJSDocCommentsToNewNode(member, newNode);
929
929
  classMembers.push(newNode);
930
930
  } else {
931
+ const [key, computed] = (() => {
932
+ const _key = member.key;
933
+ if (_key.type === 'Identifier' && _key.name.startsWith('@@')) {
934
+ const name = _key.name.slice(2);
935
+ if (['iterator', 'asyncIterator'].includes(name)) {
936
+ return [
937
+ {
938
+ type: 'MemberExpression',
939
+ computed: false,
940
+ object: {
941
+ type: 'Identifier',
942
+ name: 'Symbol',
943
+ optional: false,
944
+ loc: DUMMY_LOC,
945
+ },
946
+ optional: false,
947
+ property: {
948
+ type: 'Identifier',
949
+ name,
950
+ optional: false,
951
+ loc: DUMMY_LOC,
952
+ },
953
+ loc: DUMMY_LOC,
954
+ },
955
+ true,
956
+ ];
957
+ }
958
+ }
959
+
960
+ return [member.key, member.computed];
961
+ })();
962
+
931
963
  const newNode: TSESTree.MethodDefinitionAmbiguous = {
932
964
  type: 'MethodDefinition',
933
965
  loc: DUMMY_LOC,
934
966
  accessibility: member.accessibility,
935
- computed: member.computed ?? false,
936
- key: member.key,
967
+ computed: computed ?? false,
968
+ key,
937
969
  kind: member.kind,
938
970
  optional: member.optional,
939
971
  override: false,
@@ -1030,8 +1062,9 @@ const getTransforms = (
1030
1062
  superClass:
1031
1063
  superClass == null
1032
1064
  ? null
1033
- : // Bug: superclass.id can be qualified
1034
- transform.Identifier((superClass.id: $FlowFixMe), false),
1065
+ : superClass.id.type === 'QualifiedTypeIdentifier'
1066
+ ? transform.QualifiedTypeIdentifier(superClass.id)
1067
+ : transform.Identifier((superClass.id: $FlowFixMe), false),
1035
1068
  superTypeParameters:
1036
1069
  superClass?.typeParameters == null
1037
1070
  ? undefined
@@ -1057,6 +1090,16 @@ const getTransforms = (
1057
1090
  | TSESTree.TSTypeAliasDeclaration
1058
1091
  ),
1059
1092
  TSESTree.ExportDefaultDeclaration,
1093
+ ]
1094
+ | [
1095
+ (
1096
+ | TSESTree.VariableDeclaration
1097
+ | TSESTree.ClassDeclaration
1098
+ | TSESTree.TSDeclareFunction
1099
+ | TSESTree.TSTypeAliasDeclaration
1100
+ ),
1101
+ TSESTree.TSTypeAliasDeclaration,
1102
+ TSESTree.ExportDefaultDeclaration,
1060
1103
  ] {
1061
1104
  if (node.default === true) {
1062
1105
  const declaration = node.declaration;
@@ -1204,6 +1247,38 @@ const getTransforms = (
1204
1247
  // intentional fallthrough to the "default" handling
1205
1248
  }
1206
1249
 
1250
+ case 'TypeofTypeAnnotation': {
1251
+ if (
1252
+ declaration.type === 'TypeofTypeAnnotation' &&
1253
+ declaration.argument.type === 'Identifier'
1254
+ ) {
1255
+ const name = declaration.argument.name;
1256
+ const exportedVar = topScope.set.get(name);
1257
+ if (exportedVar != null && exportedVar.defs.length === 1) {
1258
+ const def = exportedVar.defs[0];
1259
+
1260
+ switch (def.type) {
1261
+ case 'ClassName': {
1262
+ return {
1263
+ type: 'ExportDefaultDeclaration',
1264
+ declaration: {
1265
+ type: 'Identifier',
1266
+ decorators: [],
1267
+ name,
1268
+ optional: false,
1269
+ loc: DUMMY_LOC,
1270
+ },
1271
+ exportKind: 'value',
1272
+ loc: DUMMY_LOC,
1273
+ };
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ // intentional fallthrough to the "default" handling
1280
+ }
1281
+
1207
1282
  default: {
1208
1283
  /*
1209
1284
  flow allows syntax like
@@ -1243,6 +1318,29 @@ const getTransforms = (
1243
1318
  declare: true,
1244
1319
  kind: 'const',
1245
1320
  },
1321
+ {
1322
+ type: 'TSTypeAliasDeclaration',
1323
+ declare: true,
1324
+ id: {
1325
+ type: 'Identifier',
1326
+ decorators: [],
1327
+ name: SPECIFIER,
1328
+ optional: false,
1329
+ loc: DUMMY_LOC,
1330
+ },
1331
+ typeAnnotation: {
1332
+ type: 'TSTypeQuery',
1333
+ exprName: {
1334
+ type: 'Identifier',
1335
+ decorators: [],
1336
+ name: SPECIFIER,
1337
+ optional: false,
1338
+ loc: DUMMY_LOC,
1339
+ },
1340
+ loc: DUMMY_LOC,
1341
+ },
1342
+ loc: DUMMY_LOC,
1343
+ },
1246
1344
  {
1247
1345
  type: 'ExportDefaultDeclaration',
1248
1346
  loc: DUMMY_LOC,
@@ -1343,9 +1441,66 @@ const getTransforms = (
1343
1441
  }
1344
1442
  })();
1345
1443
 
1346
- return declarations.map(
1347
- ({declaration, exportKind}) =>
1348
- ({
1444
+ const mappedDeclarations: Array<
1445
+ | TSESTree.ExportNamedDeclaration
1446
+ | Array<TSESTree.ExportNamedDeclaration>,
1447
+ > = declarations.map(({declaration, exportKind}) => {
1448
+ if (
1449
+ declaration.type === 'VariableDeclaration' &&
1450
+ declaration.declarations.length === 1
1451
+ ) {
1452
+ const ident = declaration.declarations[0].id;
1453
+ if (ident.type === 'Identifier') {
1454
+ const name = ident.name;
1455
+ return [
1456
+ {
1457
+ type: 'ExportNamedDeclaration',
1458
+ loc: DUMMY_LOC,
1459
+ // flow does not currently support assertions
1460
+ assertions: [],
1461
+ declaration,
1462
+ exportKind,
1463
+ source: null,
1464
+ specifiers: [],
1465
+ },
1466
+ {
1467
+ type: 'ExportNamedDeclaration',
1468
+ declaration: {
1469
+ type: 'TSTypeAliasDeclaration',
1470
+ declare: true,
1471
+ id: {
1472
+ type: 'Identifier',
1473
+ decorators: [],
1474
+ name,
1475
+ optional: false,
1476
+ loc: DUMMY_LOC,
1477
+ },
1478
+ typeAnnotation: {
1479
+ type: 'TSTypeQuery',
1480
+ exprName: {
1481
+ type: 'Identifier',
1482
+ decorators: [],
1483
+ name,
1484
+ optional: false,
1485
+ loc: DUMMY_LOC,
1486
+ },
1487
+ loc: DUMMY_LOC,
1488
+ },
1489
+ loc: DUMMY_LOC,
1490
+ },
1491
+ source: null,
1492
+ loc: DUMMY_LOC,
1493
+ specifiers: [],
1494
+ exportKind: 'type',
1495
+ // flow does not currently support assertions
1496
+ assertions: [],
1497
+ },
1498
+ ];
1499
+ }
1500
+ }
1501
+
1502
+ const exportNamedDeclaration: TSESTree.ExportNamedDeclarationWithoutSourceWithSingle =
1503
+ {
1349
1504
  type: 'ExportNamedDeclaration',
1350
1505
  loc: DUMMY_LOC,
1351
1506
  // flow does not currently support assertions
@@ -1354,8 +1509,11 @@ const getTransforms = (
1354
1509
  exportKind,
1355
1510
  source: null,
1356
1511
  specifiers: [],
1357
- }: TSESTree.ExportNamedDeclarationWithoutSourceWithSingle),
1358
- );
1512
+ };
1513
+ return exportNamedDeclaration;
1514
+ });
1515
+
1516
+ return mappedDeclarations.flat();
1359
1517
  } else {
1360
1518
  return ({
1361
1519
  type: 'ExportNamedDeclaration',
@@ -1611,6 +1769,50 @@ const getTransforms = (
1611
1769
  // TODO - we could simulate this in a variety of ways
1612
1770
  // Examples - https://basarat.gitbook.io/typescript/main-1/nominaltyping
1613
1771
 
1772
+ if (node.supertype == null && node.typeParameters == null) {
1773
+ const name = `__${node.id.name}__`;
1774
+ return {
1775
+ type: 'TSTypeAliasDeclaration',
1776
+ loc: DUMMY_LOC,
1777
+ declare: true,
1778
+ id: transform.Identifier(node.id, false),
1779
+ typeAnnotation: {
1780
+ type: 'TSIntersectionType',
1781
+ types: [
1782
+ {
1783
+ type: 'TSSymbolKeyword',
1784
+ loc: DUMMY_LOC,
1785
+ },
1786
+ {
1787
+ type: 'TSTypeLiteral',
1788
+ loc: DUMMY_LOC,
1789
+ members: [
1790
+ {
1791
+ type: 'TSPropertySignature',
1792
+ computed: false,
1793
+ loc: DUMMY_LOC,
1794
+ key: {
1795
+ type: 'Identifier',
1796
+ name: name,
1797
+ loc: DUMMY_LOC,
1798
+ },
1799
+ typeAnnotation: {
1800
+ type: 'TSTypeAnnotation',
1801
+ loc: DUMMY_LOC,
1802
+ typeAnnotation: {
1803
+ type: 'TSStringKeyword',
1804
+ loc: DUMMY_LOC,
1805
+ },
1806
+ },
1807
+ },
1808
+ ],
1809
+ },
1810
+ ],
1811
+ loc: DUMMY_LOC,
1812
+ },
1813
+ };
1814
+ }
1815
+
1614
1816
  return {
1615
1817
  type: 'TSTypeAliasDeclaration',
1616
1818
  loc: DUMMY_LOC,
@@ -1971,6 +2173,24 @@ const getTransforms = (
1971
2173
  return unsupportedAnnotation(node, fullTypeName);
1972
2174
  }
1973
2175
 
2176
+ case '$ArrayLike': {
2177
+ // `$ArrayLike<T>` => `ArrayLike<T>`
2178
+ return {
2179
+ type: 'TSTypeReference',
2180
+ loc: DUMMY_LOC,
2181
+ typeName: {
2182
+ type: 'Identifier',
2183
+ loc: DUMMY_LOC,
2184
+ name: 'ArrayLike',
2185
+ },
2186
+ typeParameters: {
2187
+ type: 'TSTypeParameterInstantiation',
2188
+ loc: DUMMY_LOC,
2189
+ params: assertHasExactlyNTypeParameters(1),
2190
+ },
2191
+ };
2192
+ }
2193
+
1974
2194
  case '$Diff':
1975
2195
  case '$Rest': {
1976
2196
  // `$Diff<A, B>` => `Pick<A, Exclude<keyof A, keyof B>>`
@@ -2587,7 +2807,7 @@ const getTransforms = (
2587
2807
  },
2588
2808
  },
2589
2809
  };
2590
- // React.MixedElement -> JSX.Element
2810
+ // React.MixedElement -> React.JSX.Element
2591
2811
  case 'React$MixedElement':
2592
2812
  case 'React.MixedElement': {
2593
2813
  assertHasExactlyNTypeParameters(0);
@@ -2598,9 +2818,18 @@ const getTransforms = (
2598
2818
  type: 'TSQualifiedName',
2599
2819
  loc: DUMMY_LOC,
2600
2820
  left: {
2601
- type: 'Identifier',
2821
+ type: 'TSQualifiedName',
2602
2822
  loc: DUMMY_LOC,
2603
- name: 'JSX',
2823
+ left: {
2824
+ type: 'Identifier',
2825
+ loc: DUMMY_LOC,
2826
+ name: 'React',
2827
+ },
2828
+ right: {
2829
+ type: 'Identifier',
2830
+ loc: DUMMY_LOC,
2831
+ name: 'JSX',
2832
+ },
2604
2833
  },
2605
2834
  right: {
2606
2835
  type: 'Identifier',
@@ -2742,8 +2971,8 @@ const getTransforms = (
2742
2971
  },
2743
2972
  };
2744
2973
  }
2745
- // React.ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2746
- // React$ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2974
+ // React.ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2975
+ // React$ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
2747
2976
  case 'React.ElementConfig':
2748
2977
  case 'React$ElementConfig': {
2749
2978
  const [param] = assertHasExactlyNTypeParameters(1);
@@ -2754,9 +2983,18 @@ const getTransforms = (
2754
2983
  type: 'TSQualifiedName',
2755
2984
  loc: DUMMY_LOC,
2756
2985
  left: {
2757
- type: 'Identifier',
2986
+ type: 'TSQualifiedName',
2758
2987
  loc: DUMMY_LOC,
2759
- name: 'JSX',
2988
+ left: {
2989
+ type: 'Identifier',
2990
+ loc: DUMMY_LOC,
2991
+ name: 'React',
2992
+ },
2993
+ right: {
2994
+ type: 'Identifier',
2995
+ loc: DUMMY_LOC,
2996
+ name: 'JSX',
2997
+ },
2760
2998
  },
2761
2999
  right: {
2762
3000
  type: 'Identifier',
@@ -2963,8 +3201,10 @@ const getTransforms = (
2963
3201
  return {
2964
3202
  type: 'TSInterfaceHeritage',
2965
3203
  loc: DUMMY_LOC,
2966
- // Bug: node.id can be qualified
2967
- expression: transform.Identifier((node.id: $FlowFixMe), false),
3204
+ expression:
3205
+ node.id.type === 'QualifiedTypeIdentifier'
3206
+ ? transform.QualifiedTypeIdentifier(node.id)
3207
+ : transform.Identifier(node.id, false),
2968
3208
  typeParameters:
2969
3209
  node.typeParameters == null
2970
3210
  ? undefined
@@ -3285,7 +3525,10 @@ const getTransforms = (
3285
3525
  }
3286
3526
 
3287
3527
  const spreadType = transformTypeAnnotationType(property.argument);
3288
- if (spreadType.type !== 'TSTypeReference') {
3528
+ if (
3529
+ spreadType.type !== 'TSTypeReference' &&
3530
+ spreadType.type !== 'TSTypeQuery'
3531
+ ) {
3289
3532
  return unsupportedAnnotation(
3290
3533
  property,
3291
3534
  'object types with complex spreads',
@@ -3371,7 +3614,38 @@ const getTransforms = (
3371
3614
  },
3372
3615
  ObjectTypeIndexer(
3373
3616
  node: FlowESTree.ObjectTypeIndexer,
3374
- ): TSESTree.TSIndexSignature {
3617
+ ): TSESTree.TSIndexSignature | TSESTree.TSPropertySignatureComputedName {
3618
+ if (node.key.type === 'GenericTypeAnnotation') {
3619
+ const ident =
3620
+ node.key.id.type === 'Identifier' ? node.key.id : node.key.id.id;
3621
+ return {
3622
+ type: 'TSPropertySignature',
3623
+ computed: true,
3624
+ loc: DUMMY_LOC,
3625
+ key: {
3626
+ type: 'BinaryExpression',
3627
+ operator: 'in',
3628
+ loc: DUMMY_LOC,
3629
+ left: {
3630
+ type: 'Identifier',
3631
+ name: node.id == null ? '$$Key$$' : node.id.name,
3632
+ loc: DUMMY_LOC,
3633
+ },
3634
+ right: {
3635
+ type: 'Identifier',
3636
+ name: ident.name,
3637
+ loc: DUMMY_LOC,
3638
+ },
3639
+ },
3640
+ readonly: node.variance?.kind === 'plus',
3641
+ static: node.static,
3642
+ typeAnnotation: {
3643
+ type: 'TSTypeAnnotation',
3644
+ loc: DUMMY_LOC,
3645
+ typeAnnotation: transformTypeAnnotationType(node.value),
3646
+ },
3647
+ };
3648
+ }
3375
3649
  return {
3376
3650
  type: 'TSIndexSignature',
3377
3651
  loc: DUMMY_LOC,
@@ -69,9 +69,9 @@ function transferProgramStatementProperties(stmt, orgStmt) {
69
69
  stmt.loc = orgStmt.loc;
70
70
  }
71
71
  /**
72
- * Consume an abribray Flow AST and convert it into a Type defintion file.
72
+ * Consume an arbitrary Flow AST and convert it into a type definition file.
73
73
  *
74
- * To do this all runtime logic will be stripped and only Type that describe the module boundary will remain.
74
+ * To do this all runtime logic will be stripped and only types that describe the module boundary will remain.
75
75
  */
76
76
 
77
77
 
@@ -355,8 +355,8 @@ function convertExpressionToTypeAnnotation(expr, context) {
355
355
 
356
356
  case 'Identifier':
357
357
  {
358
- return [_hermesTransform.t.GenericTypeAnnotation({
359
- id: _hermesTransform.t.Identifier({
358
+ return [_hermesTransform.t.TypeofTypeAnnotation({
359
+ argument: _hermesTransform.t.Identifier({
360
360
  name: expr.name
361
361
  })
362
362
  }), (0, _FlowAnalyze.analyzeTypeDependencies)(expr, context)];
@@ -381,6 +381,13 @@ function convertExpressionToTypeAnnotation(expr, context) {
381
381
  return [resultExpr, deps];
382
382
  }
383
383
 
384
+ case 'MemberExpression':
385
+ {
386
+ return [_hermesTransform.t.TypeofTypeAnnotation({
387
+ argument: convertExpressionToTypeofIdentifier(expr, context)
388
+ }), (0, _FlowAnalyze.analyzeTypeDependencies)(expr, context)];
389
+ }
390
+
384
391
  default:
385
392
  {
386
393
  return [(0, _ErrorUtils.flowFixMeOrError)(expr, `convertExpressionToTypeAnnotation: Unsupported expression of type "${expr.type}", a type annotation is required.`, context), []];
@@ -388,6 +395,12 @@ function convertExpressionToTypeAnnotation(expr, context) {
388
395
  }
389
396
  }
390
397
 
398
+ function inheritComments(fromNode, toNode) {
399
+ // $FlowFixMe[unclear-type]
400
+ toNode.comments = fromNode.comments;
401
+ return toNode;
402
+ }
403
+
391
404
  function convertObjectExpression(expr, context) {
392
405
  const [resultProperties, deps] = convertArray(expr.properties, prop => {
393
406
  switch (prop.type) {
@@ -411,11 +424,11 @@ function convertObjectExpression(expr, context) {
411
424
  }
412
425
 
413
426
  const [resultExpr, deps] = convertAFunction(prop.value, context);
414
- return [_hermesTransform.t.ObjectTypeMethodSignature({
427
+ return [inheritComments(prop, _hermesTransform.t.ObjectTypeMethodSignature({
415
428
  // $FlowFixMe[incompatible-call]
416
429
  key: (0, _hermesTransform.asDetachedNode)(prop.key),
417
430
  value: resultExpr
418
- }), deps];
431
+ })), deps];
419
432
  }
420
433
 
421
434
  if (prop.kind === 'get' || prop.kind === 'set') {
@@ -425,22 +438,22 @@ function convertObjectExpression(expr, context) {
425
438
 
426
439
  const kind = prop.kind;
427
440
  const [resultExpr, deps] = convertAFunction(prop.value, context);
428
- return [_hermesTransform.t.ObjectTypeAccessorSignature({
441
+ return [inheritComments(prop, _hermesTransform.t.ObjectTypeAccessorSignature({
429
442
  // $FlowFixMe[incompatible-call]
430
443
  key: (0, _hermesTransform.asDetachedNode)(prop.key),
431
444
  kind,
432
445
  value: resultExpr
433
- }), deps];
446
+ })), deps];
434
447
  }
435
448
 
436
449
  const [resultExpr, deps] = convertExpressionToTypeAnnotation(prop.value, context);
437
- return [_hermesTransform.t.ObjectTypePropertySignature({
450
+ return [inheritComments(prop, _hermesTransform.t.ObjectTypePropertySignature({
438
451
  // $FlowFixMe[incompatible-call]
439
452
  key: (0, _hermesTransform.asDetachedNode)(prop.key),
440
453
  value: resultExpr,
441
454
  optional: false,
442
455
  variance: null
443
- }), deps];
456
+ })), deps];
444
457
  }
445
458
  }
446
459
  });
@@ -777,6 +790,32 @@ function convertExpressionToIdentifier(node, context) {
777
790
  throw (0, _ErrorUtils.translationError)(node, `Expected ${node.type} to be an Identifier or Member with Identifier property, non-Super object.`, context);
778
791
  }
779
792
 
793
+ function convertExpressionToTypeofIdentifier(node, context) {
794
+ if (node.type === 'Identifier') {
795
+ return _hermesTransform.t.Identifier({
796
+ name: node.name
797
+ });
798
+ }
799
+
800
+ if (node.type === 'MemberExpression') {
801
+ const {
802
+ property,
803
+ object
804
+ } = node;
805
+
806
+ if (property.type === 'Identifier' && object.type !== 'Super') {
807
+ return _hermesTransform.t.QualifiedTypeofIdentifier({
808
+ qualification: convertExpressionToTypeofIdentifier(object, context),
809
+ id: _hermesTransform.t.Identifier({
810
+ name: property.name
811
+ })
812
+ });
813
+ }
814
+ }
815
+
816
+ throw (0, _ErrorUtils.translationError)(node, `Expected ${node.type} to be an Identifier or Member with Identifier property, non-Super object.`, context);
817
+ }
818
+
780
819
  function convertSuperClassHelper(detachedId, nodeForDependencies, superTypeParameters, context) {
781
820
  const [resultTypeParams, typeParamsDeps] = convertTypeParameterInstantiationOrNull(superTypeParameters, context);
782
821
  const superDeps = (0, _FlowAnalyze.analyzeTypeDependencies)(nodeForDependencies, context);
@@ -845,6 +884,8 @@ function convertClassMember(member, context) {
845
884
  switch (member.type) {
846
885
  case 'PropertyDefinition':
847
886
  {
887
+ var _member$value;
888
+
848
889
  // PrivateIdentifier's are not exposed so can be stripped.
849
890
  if (member.key.type === 'PrivateIdentifier') {
850
891
  return EMPTY_TRANSLATION_RESULT;
@@ -854,6 +895,18 @@ function convertClassMember(member, context) {
854
895
  throw (0, _ErrorUtils.translationError)(member.key, `ClassMember PropertyDefinition: Unsupported key type of "${member.key.type}"`, context);
855
896
  }
856
897
 
898
+ if (((_member$value = member.value) == null ? void 0 : _member$value.type) === 'ArrowFunctionExpression' && member.typeAnnotation == null) {
899
+ const [resultTypeAnnotation, deps] = convertAFunction(member.value, context);
900
+ return [_hermesTransform.t.ObjectTypePropertySignature({
901
+ // $FlowFixMe[incompatible-call]
902
+ key: (0, _hermesTransform.asDetachedNode)(member.key),
903
+ value: resultTypeAnnotation,
904
+ optional: member.optional,
905
+ static: member.static,
906
+ variance: member.variance
907
+ }), deps];
908
+ }
909
+
857
910
  const [resultTypeAnnotation, deps] = convertTypeAnnotation(member.typeAnnotation, member, context);
858
911
  return [_hermesTransform.t.ObjectTypePropertySignature({
859
912
  // $FlowFixMe[incompatible-call]
@@ -872,18 +925,21 @@ function convertClassMember(member, context) {
872
925
  return EMPTY_TRANSLATION_RESULT;
873
926
  }
874
927
 
875
- if (!(0, _hermesEstree.isIdentifier)(member.key) && !(0, _hermesEstree.isStringLiteral)(member.key) && !(0, _hermesEstree.isNumericLiteral)(member.key)) {
928
+ if (!(0, _hermesEstree.isIdentifier)(member.key) && !(0, _hermesEstree.isStringLiteral)(member.key) && !(0, _hermesEstree.isNumericLiteral)(member.key) && !((0, _hermesEstree.isMemberExpressionWithNonComputedProperty)(member.key) && member.key.object.type === 'Identifier' && member.key.object.name === 'Symbol' && ['iterator', 'asyncIterator'].includes(member.key.property.name))) {
876
929
  throw (0, _ErrorUtils.translationError)(member.key, `ClassMember PropertyDefinition: Unsupported key type of "${member.key.type}"`, context);
877
930
  }
878
931
 
879
932
  const [resultValue, deps] = convertAFunction(member.value, context);
933
+ const newKey = (0, _hermesEstree.isMemberExpressionWithNonComputedProperty)(member.key) && member.key.object.type === 'Identifier' && member.key.object.name === 'Symbol' ? _hermesTransform.t.Identifier({
934
+ name: `@@${member.key.property.name}`
935
+ }) : member.key;
880
936
 
881
937
  if (member.kind === 'get' || member.kind === 'set') {
882
938
  // accessors are methods - but flow accessor signatures are properties
883
939
  const kind = member.kind;
884
940
  return [_hermesTransform.t.ObjectTypeAccessorSignature({
885
941
  // $FlowFixMe[incompatible-call]
886
- key: (0, _hermesTransform.asDetachedNode)(member.key),
942
+ key: (0, _hermesTransform.asDetachedNode)(newKey),
887
943
  value: resultValue,
888
944
  static: member.static,
889
945
  kind
@@ -892,7 +948,7 @@ function convertClassMember(member, context) {
892
948
 
893
949
  return [_hermesTransform.t.ObjectTypeMethodSignature({
894
950
  // $FlowFixMe[incompatible-call]
895
- key: (0, _hermesTransform.asDetachedNode)(member.key),
951
+ key: (0, _hermesTransform.asDetachedNode)(newKey),
896
952
  value: resultValue,
897
953
  static: member.static
898
954
  }), deps];
@@ -50,6 +50,7 @@ import type {
50
50
  ObjectTypeProperty,
51
51
  OpaqueType,
52
52
  QualifiedTypeIdentifier,
53
+ QualifiedTypeofIdentifier,
53
54
  Program,
54
55
  RestElement,
55
56
  Statement,
@@ -84,6 +85,7 @@ import {
84
85
  isStringLiteral,
85
86
  isNumericLiteral,
86
87
  isIdentifier,
88
+ isMemberExpressionWithNonComputedProperty,
87
89
  } from 'hermes-estree';
88
90
 
89
91
  const EMPTY_TRANSLATION_RESULT = [null, []];
@@ -149,9 +151,9 @@ function transferProgramStatementProperties(
149
151
  }
150
152
 
151
153
  /**
152
- * Consume an abribray Flow AST and convert it into a Type defintion file.
154
+ * Consume an arbitrary Flow AST and convert it into a type definition file.
153
155
  *
154
- * To do this all runtime logic will be stripped and only Type that describe the module boundary will remain.
156
+ * To do this all runtime logic will be stripped and only types that describe the module boundary will remain.
155
157
  */
156
158
  export default function flowToFlowDef(
157
159
  ast: Program,
@@ -443,7 +445,7 @@ function convertExpressionToTypeAnnotation(
443
445
  }
444
446
  case 'Identifier': {
445
447
  return [
446
- t.GenericTypeAnnotation({id: t.Identifier({name: expr.name})}),
448
+ t.TypeofTypeAnnotation({argument: t.Identifier({name: expr.name})}),
447
449
  analyzeTypeDependencies(expr, context),
448
450
  ];
449
451
  }
@@ -460,6 +462,14 @@ function convertExpressionToTypeAnnotation(
460
462
  const [resultExpr, deps] = convertAFunction(expr, context);
461
463
  return [resultExpr, deps];
462
464
  }
465
+ case 'MemberExpression': {
466
+ return [
467
+ t.TypeofTypeAnnotation({
468
+ argument: convertExpressionToTypeofIdentifier(expr, context),
469
+ }),
470
+ analyzeTypeDependencies(expr, context),
471
+ ];
472
+ }
463
473
  default: {
464
474
  return [
465
475
  flowFixMeOrError(
@@ -473,6 +483,15 @@ function convertExpressionToTypeAnnotation(
473
483
  }
474
484
  }
475
485
 
486
+ function inheritComments<T: DetachedNode<ESNode>>(
487
+ fromNode: ESNode,
488
+ toNode: T,
489
+ ): T {
490
+ // $FlowFixMe[unclear-type]
491
+ (toNode: any).comments = (fromNode: any).comments;
492
+ return toNode;
493
+ }
494
+
476
495
  function convertObjectExpression(
477
496
  expr: ObjectExpression,
478
497
  context: TranslationContext,
@@ -513,13 +532,16 @@ function convertObjectExpression(
513
532
 
514
533
  const [resultExpr, deps] = convertAFunction(prop.value, context);
515
534
  return [
516
- t.ObjectTypeMethodSignature({
517
- // $FlowFixMe[incompatible-call]
518
- key: asDetachedNode<
519
- Identifier | NumericLiteral | StringLiteral | Expression,
520
- >(prop.key),
521
- value: resultExpr,
522
- }),
535
+ inheritComments(
536
+ prop,
537
+ t.ObjectTypeMethodSignature({
538
+ // $FlowFixMe[incompatible-call]
539
+ key: asDetachedNode<
540
+ Identifier | NumericLiteral | StringLiteral | Expression,
541
+ >(prop.key),
542
+ value: resultExpr,
543
+ }),
544
+ ),
523
545
  deps,
524
546
  ];
525
547
  }
@@ -539,14 +561,17 @@ function convertObjectExpression(
539
561
  const kind = prop.kind;
540
562
  const [resultExpr, deps] = convertAFunction(prop.value, context);
541
563
  return [
542
- t.ObjectTypeAccessorSignature({
543
- // $FlowFixMe[incompatible-call]
544
- key: asDetachedNode<
545
- Identifier | NumericLiteral | StringLiteral | Expression,
546
- >(prop.key),
547
- kind,
548
- value: resultExpr,
549
- }),
564
+ inheritComments(
565
+ prop,
566
+ t.ObjectTypeAccessorSignature({
567
+ // $FlowFixMe[incompatible-call]
568
+ key: asDetachedNode<
569
+ Identifier | NumericLiteral | StringLiteral | Expression,
570
+ >(prop.key),
571
+ kind,
572
+ value: resultExpr,
573
+ }),
574
+ ),
550
575
  deps,
551
576
  ];
552
577
  }
@@ -557,15 +582,18 @@ function convertObjectExpression(
557
582
  );
558
583
 
559
584
  return [
560
- t.ObjectTypePropertySignature({
561
- // $FlowFixMe[incompatible-call]
562
- key: asDetachedNode<
563
- Identifier | NumericLiteral | StringLiteral | Expression,
564
- >(prop.key),
565
- value: resultExpr,
566
- optional: false,
567
- variance: null,
568
- }),
585
+ inheritComments(
586
+ prop,
587
+ t.ObjectTypePropertySignature({
588
+ // $FlowFixMe[incompatible-call]
589
+ key: asDetachedNode<
590
+ Identifier | NumericLiteral | StringLiteral | Expression,
591
+ >(prop.key),
592
+ value: resultExpr,
593
+ optional: false,
594
+ variance: null,
595
+ }),
596
+ ),
569
597
  deps,
570
598
  ];
571
599
  }
@@ -1003,6 +1031,31 @@ function convertExpressionToIdentifier(
1003
1031
  );
1004
1032
  }
1005
1033
 
1034
+ function convertExpressionToTypeofIdentifier(
1035
+ node: Expression,
1036
+ context: TranslationContext,
1037
+ ): DetachedNode<Identifier> | DetachedNode<QualifiedTypeofIdentifier> {
1038
+ if (node.type === 'Identifier') {
1039
+ return t.Identifier({name: node.name});
1040
+ }
1041
+
1042
+ if (node.type === 'MemberExpression') {
1043
+ const {property, object} = node;
1044
+ if (property.type === 'Identifier' && object.type !== 'Super') {
1045
+ return t.QualifiedTypeofIdentifier({
1046
+ qualification: convertExpressionToTypeofIdentifier(object, context),
1047
+ id: t.Identifier({name: property.name}),
1048
+ });
1049
+ }
1050
+ }
1051
+
1052
+ throw translationError(
1053
+ node,
1054
+ `Expected ${node.type} to be an Identifier or Member with Identifier property, non-Super object.`,
1055
+ context,
1056
+ );
1057
+ }
1058
+
1006
1059
  function convertSuperClassHelper(
1007
1060
  detachedId: DetachedNode<Identifier | QualifiedTypeIdentifier>,
1008
1061
  nodeForDependencies: ESNode,
@@ -1135,6 +1188,30 @@ function convertClassMember(
1135
1188
  );
1136
1189
  }
1137
1190
 
1191
+ if (
1192
+ member.value?.type === 'ArrowFunctionExpression' &&
1193
+ member.typeAnnotation == null
1194
+ ) {
1195
+ const [resultTypeAnnotation, deps] = convertAFunction(
1196
+ member.value,
1197
+ context,
1198
+ );
1199
+
1200
+ return [
1201
+ t.ObjectTypePropertySignature({
1202
+ // $FlowFixMe[incompatible-call]
1203
+ key: asDetachedNode<
1204
+ ClassPropertyNameComputed | ClassPropertyNameNonComputed,
1205
+ >(member.key),
1206
+ value: resultTypeAnnotation,
1207
+ optional: member.optional,
1208
+ static: member.static,
1209
+ variance: member.variance,
1210
+ }),
1211
+ deps,
1212
+ ];
1213
+ }
1214
+
1138
1215
  const [resultTypeAnnotation, deps] = convertTypeAnnotation(
1139
1216
  member.typeAnnotation,
1140
1217
  member,
@@ -1163,7 +1240,13 @@ function convertClassMember(
1163
1240
  if (
1164
1241
  !isIdentifier(member.key) &&
1165
1242
  !isStringLiteral(member.key) &&
1166
- !isNumericLiteral(member.key)
1243
+ !isNumericLiteral(member.key) &&
1244
+ !(
1245
+ isMemberExpressionWithNonComputedProperty(member.key) &&
1246
+ member.key.object.type === 'Identifier' &&
1247
+ member.key.object.name === 'Symbol' &&
1248
+ ['iterator', 'asyncIterator'].includes(member.key.property.name)
1249
+ )
1167
1250
  ) {
1168
1251
  throw translationError(
1169
1252
  member.key,
@@ -1174,15 +1257,23 @@ function convertClassMember(
1174
1257
 
1175
1258
  const [resultValue, deps] = convertAFunction(member.value, context);
1176
1259
 
1260
+ const newKey =
1261
+ isMemberExpressionWithNonComputedProperty(member.key) &&
1262
+ member.key.object.type === 'Identifier' &&
1263
+ member.key.object.name === 'Symbol'
1264
+ ? t.Identifier({name: `@@${member.key.property.name}`})
1265
+ : member.key;
1266
+
1177
1267
  if (member.kind === 'get' || member.kind === 'set') {
1178
1268
  // accessors are methods - but flow accessor signatures are properties
1179
1269
  const kind = member.kind;
1270
+
1180
1271
  return [
1181
1272
  t.ObjectTypeAccessorSignature({
1182
1273
  // $FlowFixMe[incompatible-call]
1183
1274
  key: asDetachedNode<
1184
1275
  ClassPropertyNameComputed | ClassPropertyNameNonComputed,
1185
- >(member.key),
1276
+ >(newKey),
1186
1277
  value: resultValue,
1187
1278
  static: member.static,
1188
1279
  kind,
@@ -1196,7 +1287,7 @@ function convertClassMember(
1196
1287
  // $FlowFixMe[incompatible-call]
1197
1288
  key: asDetachedNode<
1198
1289
  ClassPropertyNameComputed | ClassPropertyNameNonComputed,
1199
- >(member.key),
1290
+ >(newKey),
1200
1291
  value: resultValue,
1201
1292
  static: member.static,
1202
1293
  }),
@@ -455,6 +455,7 @@ export type Expression =
455
455
  | TSAsExpression
456
456
  | TSInstantiationExpression
457
457
  | TSNonNullExpression
458
+ | TSQualifiedName
458
459
  | TSTypeAssertion
459
460
  | UnaryExpression
460
461
  | UpdateExpression
@@ -772,6 +773,7 @@ export type LeftHandSideExpression =
772
773
  | ThisExpression
773
774
  | TSAsExpression
774
775
  | TSNonNullExpression
776
+ | TSQualifiedName
775
777
  | TSTypeAssertion;
776
778
  export interface LineComment extends BaseToken {
777
779
  +type: 'Line';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flow-api-translator",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
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.26.0",
17
- "hermes-estree": "0.26.0",
18
- "hermes-parser": "0.26.0",
19
- "hermes-transform": "0.26.0",
16
+ "hermes-eslint": "0.27.0",
17
+ "hermes-estree": "0.27.0",
18
+ "hermes-parser": "0.27.0",
19
+ "hermes-transform": "0.27.0",
20
20
  "typescript": "5.3.2"
21
21
  },
22
22
  "peerDependencies": {