flow-api-translator 0.36.1 → 0.37.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.
- package/dist/TSDefToFlowDef.js +38 -55
- package/dist/TSDefToFlowDef.js.flow +54 -31
- package/dist/flowDefToTSDef.js +88 -453
- package/dist/flowDefToTSDef.js.flow +104 -89
- package/dist/flowImportTo.js +0 -9
- package/dist/flowImportTo.js.flow +1 -1
- package/dist/flowToFlowDef.js +83 -47
- package/dist/flowToFlowDef.js.flow +91 -15
- package/dist/flowToJS.js +0 -9
- package/dist/index.js +1 -23
- package/dist/src/TSDefToFlowDef.js +38 -55
- package/dist/src/flowDefToTSDef.js +88 -453
- package/dist/src/flowImportTo.js +0 -9
- package/dist/src/flowToFlowDef.js +83 -47
- package/dist/src/flowToJS.js +0 -9
- package/dist/src/index.js +1 -23
- package/dist/src/utils/DocblockUtils.js +0 -10
- package/dist/src/utils/ErrorUtils.js +1 -22
- package/dist/src/utils/FlowAnalyze.js +3 -12
- package/dist/src/utils/TSNodeUtils.js +68 -0
- package/dist/src/utils/TranslationUtils.js +0 -9
- package/dist/src/utils/ts-estree-ast-types.js +0 -29
- package/dist/utils/DocblockUtils.js +0 -10
- package/dist/utils/ErrorUtils.js +1 -22
- package/dist/utils/ErrorUtils.js.flow +3 -3
- package/dist/utils/FlowAnalyze.js +3 -12
- package/dist/utils/FlowAnalyze.js.flow +6 -1
- package/dist/utils/TSNodeUtils.js +68 -0
- package/dist/utils/TSNodeUtils.js.flow +74 -0
- package/dist/utils/TranslationUtils.js +0 -9
- package/dist/utils/ts-estree-ast-types.js +0 -29
- package/dist/utils/ts-estree-ast-types.js.flow +697 -740
- package/package.json +8 -7
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
1
|
'use strict';
|
|
11
2
|
|
|
12
3
|
Object.defineProperty(exports, "__esModule", {
|
|
@@ -24,6 +15,8 @@ var _ErrorUtils = require("./utils/ErrorUtils");
|
|
|
24
15
|
|
|
25
16
|
var _DocblockUtils = require("./utils/DocblockUtils");
|
|
26
17
|
|
|
18
|
+
var _TSNodeUtils = require("./utils/TSNodeUtils");
|
|
19
|
+
|
|
27
20
|
var _os = require("os");
|
|
28
21
|
|
|
29
22
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
@@ -45,18 +38,15 @@ function constructFlowNode(node) {
|
|
|
45
38
|
return node;
|
|
46
39
|
}
|
|
47
40
|
|
|
48
|
-
const cloneJSDocCommentsToNewNode =
|
|
49
|
-
_hermesTransform.
|
|
50
|
-
const makeCommentOwnLine = // $FlowExpectedError[incompatible-type] - trust me this re-type is 100% safe
|
|
51
|
-
_hermesTransform.makeCommentOwnLine;
|
|
41
|
+
const cloneJSDocCommentsToNewNode = _hermesTransform.cloneJSDocCommentsToNewNode;
|
|
42
|
+
const makeCommentOwnLine = _hermesTransform.makeCommentOwnLine;
|
|
52
43
|
const VALID_REACT_IMPORTS = new Set(['React', 'react']);
|
|
53
44
|
|
|
54
45
|
function isValidReactImportOrGlobal(id) {
|
|
55
46
|
return VALID_REACT_IMPORTS.has(id.name) || id.name.startsWith('React$');
|
|
56
47
|
}
|
|
57
48
|
|
|
58
|
-
let shouldAddReactImport = null;
|
|
59
|
-
// If a global is in use, set a flag to indicate that we should add the import.
|
|
49
|
+
let shouldAddReactImport = null;
|
|
60
50
|
|
|
61
51
|
function getReactIdentifier(hasReactImport) {
|
|
62
52
|
if (shouldAddReactImport !== false) {
|
|
@@ -84,10 +74,7 @@ function flowDefToTSDef(originalCode, ast, scopeManager, opts) {
|
|
|
84
74
|
|
|
85
75
|
for (const node of ast.body) {
|
|
86
76
|
if (node.type in transform) {
|
|
87
|
-
const result = transform[
|
|
88
|
-
// $FlowFixMe[incompatible-type]
|
|
89
|
-
node.type]( // $FlowExpectedError[incompatible-type]
|
|
90
|
-
node);
|
|
77
|
+
const result = transform[node.type](node);
|
|
91
78
|
tsBody.push(...(Array.isArray(result) ? result : [result]));
|
|
92
79
|
} else {
|
|
93
80
|
throw (0, _ErrorUtils.unexpectedTranslationError)(node, `Unexpected node type ${node.type}`, {
|
|
@@ -156,11 +143,8 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
156
143
|
leading: true,
|
|
157
144
|
printed: false
|
|
158
145
|
};
|
|
159
|
-
code = makeCommentOwnLine(code, comment);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(_node$comments = node.comments) != null ? _node$comments : node.comments = []; // $FlowExpectedError[incompatible-type]
|
|
163
|
-
|
|
146
|
+
code = makeCommentOwnLine(code, comment);
|
|
147
|
+
(_node$comments = node.comments) != null ? _node$comments : node.comments = [];
|
|
164
148
|
node.comments.push(comment);
|
|
165
149
|
}
|
|
166
150
|
|
|
@@ -240,19 +224,15 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
240
224
|
|
|
241
225
|
currentScope = currentScope.upper;
|
|
242
226
|
}
|
|
243
|
-
})();
|
|
244
|
-
// It could be a global though if isValidReactImportOrGlobal returns true.
|
|
245
|
-
|
|
227
|
+
})();
|
|
246
228
|
|
|
247
229
|
if (variableDef == null) {
|
|
248
230
|
return false;
|
|
249
231
|
}
|
|
250
232
|
|
|
251
|
-
const def = variableDef.defs[0];
|
|
233
|
+
const def = variableDef.defs[0];
|
|
252
234
|
|
|
253
235
|
switch (def.type) {
|
|
254
|
-
// import React from 'react';
|
|
255
|
-
// import * as React from 'react';
|
|
256
236
|
case 'ImportBinding':
|
|
257
237
|
{
|
|
258
238
|
if (def.node.type === 'ImportDefaultSpecifier' || def.node.type === 'ImportNamespaceSpecifier') {
|
|
@@ -261,15 +241,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
261
241
|
|
|
262
242
|
return false;
|
|
263
243
|
}
|
|
264
|
-
// Globals
|
|
265
244
|
|
|
266
245
|
case 'ImplicitGlobalVariable':
|
|
267
246
|
{
|
|
268
247
|
return VALID_REACT_IMPORTS.has(name);
|
|
269
248
|
}
|
|
270
|
-
// TODO Handle:
|
|
271
|
-
// const React = require('react');
|
|
272
|
-
// const Something = React;
|
|
273
249
|
}
|
|
274
250
|
|
|
275
251
|
return false;
|
|
@@ -279,49 +255,10 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
279
255
|
const body = node.body;
|
|
280
256
|
|
|
281
257
|
if (body.type === 'EnumSymbolBody') {
|
|
282
|
-
/*
|
|
283
|
-
There's unfortunately no way for us to support this in a clean way.
|
|
284
|
-
We can get really close using this code:
|
|
285
|
-
```
|
|
286
|
-
declare namespace SymbolEnum {
|
|
287
|
-
export const member1: unique symbol;
|
|
288
|
-
export type member1 = typeof member1;
|
|
289
|
-
export const member2: unique symbol;
|
|
290
|
-
export type member2 = typeof member2;
|
|
291
|
-
}
|
|
292
|
-
type SymbolEnum = typeof SymbolEnum[keyof typeof SymbolEnum];
|
|
293
|
-
```
|
|
294
|
-
However as explained in https://github.com/microsoft/TypeScript/issues/43657:
|
|
295
|
-
"A unique symbol type is never transferred from one declaration to another through inference."
|
|
296
|
-
This intended behaviour in TS means that the usage of the fake-enum would look like this:
|
|
297
|
-
```
|
|
298
|
-
const value: SymbolEnum.member1 = SymbolEnum.member1;
|
|
299
|
-
// ^^^^^^^^^^^^^^^^^^ required to force TS to retain the information
|
|
300
|
-
```
|
|
301
|
-
Which is really clunky and shitty. It definitely works, but ofc it's not good.
|
|
302
|
-
We can go with this design if users are okay with it!
|
|
303
|
-
Considering how rarely used symbol enums are ATM, let's just put a pin in it for now.
|
|
304
|
-
*/
|
|
305
258
|
return unsupportedDeclaration(node, 'symbol enums', node.id, FlowESTree.isDeclareEnum(node));
|
|
306
259
|
}
|
|
307
260
|
|
|
308
261
|
if (body.type === 'EnumBooleanBody') {
|
|
309
|
-
/*
|
|
310
|
-
TODO - TS enums only allow strings or numbers as their values - not booleans.
|
|
311
|
-
This means we need a non-ts-enum representation of the enum.
|
|
312
|
-
We can support boolean enums using a construct like this:
|
|
313
|
-
```ts
|
|
314
|
-
declare namespace BooleanEnum {
|
|
315
|
-
export const member1: true;
|
|
316
|
-
export type member1 = typeof member1;
|
|
317
|
-
export const member2: false;
|
|
318
|
-
export type member2 = typeof member1;
|
|
319
|
-
}
|
|
320
|
-
declare type BooleanEnum = boolean;
|
|
321
|
-
```
|
|
322
|
-
But it's pretty clunky and ugly.
|
|
323
|
-
Considering how rarely used boolean enums are ATM, let's just put a pin in it for now.
|
|
324
|
-
*/
|
|
325
262
|
return unsupportedDeclaration(node, 'boolean enums', node.id, FlowESTree.isDeclareEnum(node));
|
|
326
263
|
}
|
|
327
264
|
|
|
@@ -332,7 +269,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
332
269
|
case 'EnumDefaultedMember':
|
|
333
270
|
{
|
|
334
271
|
if (body.type === 'EnumNumberBody') {
|
|
335
|
-
// this should be impossible!
|
|
336
272
|
throw unexpectedTranslationError(member, 'Unexpected defaulted number enum member');
|
|
337
273
|
}
|
|
338
274
|
|
|
@@ -383,22 +319,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
383
319
|
loc: DUMMY_LOC
|
|
384
320
|
},
|
|
385
321
|
members
|
|
386
|
-
},
|
|
387
|
-
// we can use declaration merging to declare these functions on the enum:
|
|
388
|
-
|
|
389
|
-
/*
|
|
390
|
-
declare enum Foo {
|
|
391
|
-
A = 1,
|
|
392
|
-
B = 2,
|
|
393
|
-
}
|
|
394
|
-
declare namespace Foo {
|
|
395
|
-
export function cast(value: number | null | undefined): Foo;
|
|
396
|
-
export function isValid(value: number | null | undefined): value is Foo;
|
|
397
|
-
export function members(): IterableIterator<Foo>;
|
|
398
|
-
export function getName(value: Foo): string;
|
|
399
|
-
}
|
|
400
|
-
*/
|
|
401
|
-
{
|
|
322
|
+
}, {
|
|
402
323
|
type: 'TSModuleDeclaration',
|
|
403
324
|
loc: DUMMY_LOC,
|
|
404
325
|
declare: true,
|
|
@@ -407,8 +328,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
407
328
|
body: {
|
|
408
329
|
type: 'TSModuleBlock',
|
|
409
330
|
loc: DUMMY_LOC,
|
|
410
|
-
body: [
|
|
411
|
-
{
|
|
331
|
+
body: [{
|
|
412
332
|
type: 'ExportNamedDeclaration',
|
|
413
333
|
loc: DUMMY_LOC,
|
|
414
334
|
declaration: {
|
|
@@ -456,8 +376,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
456
376
|
source: null,
|
|
457
377
|
exportKind: 'value',
|
|
458
378
|
assertions: []
|
|
459
|
-
},
|
|
460
|
-
{
|
|
379
|
+
}, {
|
|
461
380
|
type: 'ExportNamedDeclaration',
|
|
462
381
|
loc: DUMMY_LOC,
|
|
463
382
|
declaration: {
|
|
@@ -519,8 +438,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
519
438
|
source: null,
|
|
520
439
|
exportKind: 'value',
|
|
521
440
|
assertions: []
|
|
522
|
-
},
|
|
523
|
-
{
|
|
441
|
+
}, {
|
|
524
442
|
type: 'ExportNamedDeclaration',
|
|
525
443
|
loc: DUMMY_LOC,
|
|
526
444
|
declaration: {
|
|
@@ -546,7 +464,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
546
464
|
loc: DUMMY_LOC,
|
|
547
465
|
name: 'IterableIterator'
|
|
548
466
|
},
|
|
549
|
-
|
|
467
|
+
typeArguments: {
|
|
550
468
|
type: 'TSTypeParameterInstantiation',
|
|
551
469
|
loc: DUMMY_LOC,
|
|
552
470
|
params: [{
|
|
@@ -562,8 +480,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
562
480
|
source: null,
|
|
563
481
|
exportKind: 'value',
|
|
564
482
|
assertions: []
|
|
565
|
-
},
|
|
566
|
-
{
|
|
483
|
+
}, {
|
|
567
484
|
type: 'ExportNamedDeclaration',
|
|
568
485
|
loc: DUMMY_LOC,
|
|
569
486
|
declaration: {
|
|
@@ -765,13 +682,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
765
682
|
BigIntLiteralTypeAnnotation(node) {
|
|
766
683
|
var _node$bigint;
|
|
767
684
|
|
|
768
|
-
|
|
769
|
-
// but future proofing amirite
|
|
770
|
-
const bigint = // $FlowExpectedError[prop-missing]
|
|
771
|
-
(_node$bigint = node.bigint) != null ? _node$bigint : node.raw // estree spec is to not have a trailing `n` on this property
|
|
772
|
-
// https://github.com/estree/estree/blob/db962bb417a97effcfe9892f87fbb93c81a68584/es2020.md#bigintliteral
|
|
773
|
-
.replace(/n$/, '') // `BigInt` doesn't accept numeric separator and `bigint` property should not include numeric separator
|
|
774
|
-
.replace(/_/, '');
|
|
685
|
+
const bigint = (_node$bigint = node.bigint) != null ? _node$bigint : node.raw.replace(/n$/, '').replace(/_/, '');
|
|
775
686
|
return {
|
|
776
687
|
type: 'TSLiteralType',
|
|
777
688
|
loc: DUMMY_LOC,
|
|
@@ -826,7 +737,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
826
737
|
type: 'TSClassImplements',
|
|
827
738
|
loc: DUMMY_LOC,
|
|
828
739
|
expression: transform.Identifier(node.id, false),
|
|
829
|
-
|
|
740
|
+
typeArguments: transform.TypeParameterInstantiation(node.typeParameters)
|
|
830
741
|
};
|
|
831
742
|
},
|
|
832
743
|
|
|
@@ -839,8 +750,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
839
750
|
}
|
|
840
751
|
|
|
841
752
|
for (const member of transformedBody.members) {
|
|
842
|
-
// TS uses the real ClassDeclaration AST so we need to
|
|
843
|
-
// make the signatures real methods/properties
|
|
844
753
|
switch (member.type) {
|
|
845
754
|
case 'TSIndexSignature':
|
|
846
755
|
{
|
|
@@ -850,8 +759,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
850
759
|
|
|
851
760
|
case 'TSMethodSignature':
|
|
852
761
|
{
|
|
853
|
-
// flow just creates a method signature like any other for a constructor
|
|
854
|
-
// but the proper AST has `kind = 'constructor'`
|
|
855
762
|
const isConstructor = (() => {
|
|
856
763
|
if (member.computed === true) {
|
|
857
764
|
return false;
|
|
@@ -885,7 +792,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
885
792
|
generator: false,
|
|
886
793
|
id: null,
|
|
887
794
|
params: member.params,
|
|
888
|
-
// constructors explicitly have no return type
|
|
889
795
|
returnType: undefined,
|
|
890
796
|
typeParameters: member.typeParameters
|
|
891
797
|
}
|
|
@@ -983,22 +889,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
983
889
|
{
|
|
984
890
|
var _node$body$callProper;
|
|
985
891
|
|
|
986
|
-
/*
|
|
987
|
-
TODO - callProperties
|
|
988
|
-
It's not valid to directly declare a call property on a class in TS
|
|
989
|
-
You can do it, but it's a big complication in the AST:
|
|
990
|
-
```ts
|
|
991
|
-
declare Class {
|
|
992
|
-
// ...
|
|
993
|
-
}
|
|
994
|
-
interface ClassConstructor {
|
|
995
|
-
new (): Class;
|
|
996
|
-
// call sigs
|
|
997
|
-
(): Type;
|
|
998
|
-
}
|
|
999
|
-
```
|
|
1000
|
-
Let's put a pin in it for now and deal with it later if the need arises.
|
|
1001
|
-
*/
|
|
1002
892
|
return unsupportedDeclaration((_node$body$callProper = node.body.callProperties[0]) != null ? _node$body$callProper : node.body, 'call signatures on classes', node.id, true, node.typeParameters);
|
|
1003
893
|
}
|
|
1004
894
|
|
|
@@ -1020,9 +910,8 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1020
910
|
id: transform.Identifier(node.id, false),
|
|
1021
911
|
implements: node.implements == null ? undefined : node.implements.map(transform.ClassImplements),
|
|
1022
912
|
superClass: superClass == null ? null : superClass.id.type === 'QualifiedTypeIdentifier' ? transform.QualifiedTypeIdentifier(superClass.id) : transform.Identifier(superClass.id, false),
|
|
1023
|
-
|
|
1024
|
-
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
1025
|
-
|
|
913
|
+
superTypeArguments: transform.TypeParameterInstantiation(superClass == null ? void 0 : superClass.typeParameters),
|
|
914
|
+
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
1026
915
|
};
|
|
1027
916
|
},
|
|
1028
917
|
|
|
@@ -1031,7 +920,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1031
920
|
const declaration = node.declaration;
|
|
1032
921
|
|
|
1033
922
|
switch (declaration.type) {
|
|
1034
|
-
// TS doesn't support direct default export for declare'd classes
|
|
1035
923
|
case 'DeclareClass':
|
|
1036
924
|
{
|
|
1037
925
|
const classDecl = transform.DeclareClass(declaration);
|
|
@@ -1047,7 +935,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1047
935
|
exportKind: 'value'
|
|
1048
936
|
}];
|
|
1049
937
|
}
|
|
1050
|
-
// TS doesn't support direct default export for declare'd functions
|
|
1051
938
|
|
|
1052
939
|
case 'DeclareFunction':
|
|
1053
940
|
{
|
|
@@ -1064,7 +951,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1064
951
|
exportKind: 'value'
|
|
1065
952
|
}];
|
|
1066
953
|
}
|
|
1067
|
-
// TS doesn't support direct default export for declare'd functions
|
|
1068
954
|
|
|
1069
955
|
case 'DeclareComponent':
|
|
1070
956
|
{
|
|
@@ -1081,7 +967,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1081
967
|
exportKind: 'value'
|
|
1082
968
|
}];
|
|
1083
969
|
}
|
|
1084
|
-
// TS doesn't support direct default export for declare'd functions
|
|
1085
970
|
|
|
1086
971
|
case 'DeclareHook':
|
|
1087
972
|
{
|
|
@@ -1098,16 +983,10 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1098
983
|
exportKind: 'value'
|
|
1099
984
|
}];
|
|
1100
985
|
}
|
|
1101
|
-
// Flow's declare export default Identifier is ambiguous.
|
|
1102
|
-
// the Identifier might reference a type, or it might reference a value
|
|
1103
|
-
// - If it's a value, then that's all good, TS supports that.
|
|
1104
|
-
// - If it's a type, that's a problem - TS only allows value variables to be exported
|
|
1105
|
-
// so we need to create an intermediate variable to hold the type.
|
|
1106
986
|
|
|
1107
987
|
case 'GenericTypeAnnotation':
|
|
1108
988
|
{
|
|
1109
|
-
const referencedId = declaration.id;
|
|
1110
|
-
// only Identifiers can be handled here.
|
|
989
|
+
const referencedId = declaration.id;
|
|
1111
990
|
|
|
1112
991
|
if (referencedId.type === 'Identifier') {
|
|
1113
992
|
const exportedVar = topScope.set.get(referencedId.name);
|
|
@@ -1118,16 +997,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1118
997
|
switch (def.type) {
|
|
1119
998
|
case 'ImportBinding':
|
|
1120
999
|
{
|
|
1121
|
-
// `import type { Wut } from 'mod'; declare export default Wut;`
|
|
1122
|
-
// `import { type Wut } from 'mod'; declare export default Wut;`
|
|
1123
|
-
// these cases should be wrapped in a variable because they're exporting a type, not a value
|
|
1124
1000
|
const specifier = def.node;
|
|
1125
1001
|
|
|
1126
1002
|
if (specifier.importKind === 'type' || specifier.parent.importKind === 'type') {
|
|
1127
|
-
// fallthrough to the "default" handling
|
|
1128
1003
|
break;
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1004
|
+
}
|
|
1131
1005
|
}
|
|
1132
1006
|
|
|
1133
1007
|
case 'ClassName':
|
|
@@ -1135,7 +1009,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1135
1009
|
case 'FunctionName':
|
|
1136
1010
|
case 'ImplicitGlobalVariable':
|
|
1137
1011
|
case 'Variable':
|
|
1138
|
-
// there's already a variable defined to hold the type
|
|
1139
1012
|
return {
|
|
1140
1013
|
type: 'ExportDefaultDeclaration',
|
|
1141
1014
|
loc: DUMMY_LOC,
|
|
@@ -1153,12 +1026,10 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1153
1026
|
throw translationError(def.node, `Unexpected variable def type: ${def.type}`);
|
|
1154
1027
|
|
|
1155
1028
|
case 'Type':
|
|
1156
|
-
// fallthrough to the "default" handling
|
|
1157
1029
|
break;
|
|
1158
1030
|
}
|
|
1159
1031
|
}
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1032
|
+
}
|
|
1162
1033
|
}
|
|
1163
1034
|
|
|
1164
1035
|
case 'TypeofTypeAnnotation':
|
|
@@ -1188,24 +1059,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1188
1059
|
}
|
|
1189
1060
|
}
|
|
1190
1061
|
}
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1062
|
+
}
|
|
1193
1063
|
}
|
|
1194
1064
|
|
|
1195
1065
|
default:
|
|
1196
1066
|
{
|
|
1197
|
-
/*
|
|
1198
|
-
flow allows syntax like
|
|
1199
|
-
```
|
|
1200
|
-
declare export default TypeName;
|
|
1201
|
-
```
|
|
1202
|
-
but TS does not, so we have to declare a temporary variable to
|
|
1203
|
-
reference in the export declaration:
|
|
1204
|
-
```
|
|
1205
|
-
declare const $$EXPORT_DEFAULT_DECLARATION$$: TypeName;
|
|
1206
|
-
export default $$EXPORT_DEFAULT_DECLARATION$$;
|
|
1207
|
-
```
|
|
1208
|
-
*/
|
|
1209
1067
|
const SPECIFIER = '$$EXPORT_DEFAULT_DECLARATION$$';
|
|
1210
1068
|
return [{
|
|
1211
1069
|
type: 'VariableDeclaration',
|
|
@@ -1262,17 +1120,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1262
1120
|
}
|
|
1263
1121
|
}
|
|
1264
1122
|
} else {
|
|
1265
|
-
// eslint-disable-next-line eqeqeq
|
|
1266
1123
|
if (node.source === null) {
|
|
1267
|
-
// eslint-disable-next-line eqeqeq
|
|
1268
1124
|
if (node.declaration === null) {
|
|
1269
1125
|
return {
|
|
1270
1126
|
type: 'ExportNamedDeclaration',
|
|
1271
1127
|
loc: DUMMY_LOC,
|
|
1272
|
-
// flow does not currently support attributes
|
|
1273
1128
|
assertions: [],
|
|
1274
1129
|
declaration: null,
|
|
1275
|
-
// flow does not support declared type exports with specifiers
|
|
1276
1130
|
exportKind: 'value',
|
|
1277
1131
|
source: null,
|
|
1278
1132
|
specifiers: node.specifiers.map(transform.ExportSpecifier)
|
|
@@ -1352,7 +1206,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1352
1206
|
return [{
|
|
1353
1207
|
type: 'ExportNamedDeclaration',
|
|
1354
1208
|
loc: DUMMY_LOC,
|
|
1355
|
-
// flow does not currently support attributes
|
|
1356
1209
|
assertions: [],
|
|
1357
1210
|
declaration,
|
|
1358
1211
|
exportKind,
|
|
@@ -1387,7 +1240,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1387
1240
|
loc: DUMMY_LOC,
|
|
1388
1241
|
specifiers: [],
|
|
1389
1242
|
exportKind: 'type',
|
|
1390
|
-
// flow does not currently support attributes
|
|
1391
1243
|
assertions: []
|
|
1392
1244
|
}];
|
|
1393
1245
|
}
|
|
@@ -1396,7 +1248,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1396
1248
|
const exportNamedDeclaration = {
|
|
1397
1249
|
type: 'ExportNamedDeclaration',
|
|
1398
1250
|
loc: DUMMY_LOC,
|
|
1399
|
-
// flow does not currently support attributes
|
|
1400
1251
|
assertions: [],
|
|
1401
1252
|
declaration,
|
|
1402
1253
|
exportKind,
|
|
@@ -1410,10 +1261,8 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1410
1261
|
return {
|
|
1411
1262
|
type: 'ExportNamedDeclaration',
|
|
1412
1263
|
loc: DUMMY_LOC,
|
|
1413
|
-
// flow does not currently support attributes
|
|
1414
1264
|
assertions: [],
|
|
1415
1265
|
declaration: null,
|
|
1416
|
-
// flow does not support declared type exports with a source
|
|
1417
1266
|
exportKind: 'value',
|
|
1418
1267
|
source: transform.StringLiteral(node.source),
|
|
1419
1268
|
specifiers: node.specifiers.map(transform.ExportSpecifier)
|
|
@@ -1425,13 +1274,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1425
1274
|
DeclareComponent(node) {
|
|
1426
1275
|
const id = transform.Identifier(node.id, false);
|
|
1427
1276
|
const typeParameters = node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters);
|
|
1428
|
-
const params = transform.ComponentTypeParameters(node.params, node.rest);
|
|
1429
|
-
|
|
1277
|
+
const params = transform.ComponentTypeParameters(node.params, node.rest);
|
|
1430
1278
|
const hasReactImport = isReactImport(node, 'React');
|
|
1431
1279
|
const returnType = {
|
|
1432
1280
|
type: 'TSTypeAnnotation',
|
|
1433
1281
|
loc: DUMMY_LOC,
|
|
1434
|
-
// If no rendersType we assume its ReactNode type.
|
|
1435
1282
|
typeAnnotation: {
|
|
1436
1283
|
type: 'TSTypeReference',
|
|
1437
1284
|
loc: DUMMY_LOC,
|
|
@@ -1445,7 +1292,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1445
1292
|
name: `ReactNode`
|
|
1446
1293
|
}
|
|
1447
1294
|
},
|
|
1448
|
-
|
|
1295
|
+
typeArguments: undefined
|
|
1449
1296
|
}
|
|
1450
1297
|
};
|
|
1451
1298
|
return {
|
|
@@ -1540,7 +1387,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1540
1387
|
},
|
|
1541
1388
|
|
|
1542
1389
|
DeclareHook(node) {
|
|
1543
|
-
// the hook params/returnType are stored as an annotation on the ID...
|
|
1544
1390
|
const id = transform.Identifier(node.id, false);
|
|
1545
1391
|
const functionInfo = transform.FunctionTypeAnnotation(node.id.typeAnnotation.typeAnnotation);
|
|
1546
1392
|
return {
|
|
@@ -1563,7 +1409,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1563
1409
|
},
|
|
1564
1410
|
|
|
1565
1411
|
DeclareFunction(node) {
|
|
1566
|
-
// the function information is stored as an annotation on the ID...
|
|
1567
1412
|
const id = transform.Identifier(node.id, false);
|
|
1568
1413
|
const functionInfo = transform.FunctionTypeAnnotation(node.id.typeAnnotation.typeAnnotation);
|
|
1569
1414
|
return {
|
|
@@ -1619,9 +1464,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1619
1464
|
},
|
|
1620
1465
|
|
|
1621
1466
|
DeclareOpaqueType(node) {
|
|
1622
|
-
// TS doesn't currently have nominal types - https://github.com/Microsoft/Typescript/issues/202
|
|
1623
|
-
// TODO - we could simulate this in a variety of ways
|
|
1624
|
-
// Examples - https://basarat.gitbook.io/typescript/main-1/nominaltyping
|
|
1625
1467
|
if (node.supertype == null && node.typeParameters == null) {
|
|
1626
1468
|
const name = `__${node.id.name}__`;
|
|
1627
1469
|
return {
|
|
@@ -1695,10 +1537,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1695
1537
|
},
|
|
1696
1538
|
|
|
1697
1539
|
EmptyTypeAnnotation(node) {
|
|
1698
|
-
// Flow's `empty` type doesn't map well to any types in TS.
|
|
1699
|
-
// The closest is `never`, but `never` has a number of different semantics
|
|
1700
|
-
// In reality no human code should ever directly use the `empty` type in flow
|
|
1701
|
-
// So let's put a pin in it for now
|
|
1702
1540
|
return unsupportedAnnotation(node, 'empty type');
|
|
1703
1541
|
},
|
|
1704
1542
|
|
|
@@ -1711,8 +1549,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1711
1549
|
},
|
|
1712
1550
|
|
|
1713
1551
|
ExistsTypeAnnotation(node) {
|
|
1714
|
-
// The existential type does not map to any types in TS
|
|
1715
|
-
// It's also super deprecated - so let's not ever worry
|
|
1716
1552
|
return unsupportedAnnotation(node, 'existential type');
|
|
1717
1553
|
},
|
|
1718
1554
|
|
|
@@ -1720,7 +1556,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1720
1556
|
return {
|
|
1721
1557
|
type: 'ExportAllDeclaration',
|
|
1722
1558
|
loc: DUMMY_LOC,
|
|
1723
|
-
// flow does not currently support import/export attributes
|
|
1724
1559
|
assertions: [],
|
|
1725
1560
|
exportKind: node.exportKind,
|
|
1726
1561
|
source: transform.StringLiteral(node.source),
|
|
@@ -1730,11 +1565,9 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1730
1565
|
|
|
1731
1566
|
ExportNamedDeclaration(node) {
|
|
1732
1567
|
if (node.source != null || node.specifiers.length > 0) {
|
|
1733
|
-
// can never have a declaration with a source
|
|
1734
1568
|
return {
|
|
1735
1569
|
type: 'ExportNamedDeclaration',
|
|
1736
1570
|
loc: DUMMY_LOC,
|
|
1737
|
-
// flow does not currently support import/export attributes
|
|
1738
1571
|
assertions: [],
|
|
1739
1572
|
declaration: null,
|
|
1740
1573
|
exportKind: node.exportKind,
|
|
@@ -1755,8 +1588,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1755
1588
|
case 'HookDeclaration':
|
|
1756
1589
|
case 'FunctionDeclaration':
|
|
1757
1590
|
case 'VariableDeclaration':
|
|
1758
|
-
// These cases shouldn't happen in flow defs because they have their own special
|
|
1759
|
-
// AST node (DeclareClass, DeclareFunction, DeclareVariable)
|
|
1760
1591
|
throw unexpectedTranslationError(node.declaration, `Unexpected named declaration found ${node.declaration.type}`);
|
|
1761
1592
|
|
|
1762
1593
|
case 'EnumDeclaration':
|
|
@@ -1787,7 +1618,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1787
1618
|
};
|
|
1788
1619
|
|
|
1789
1620
|
if (mergedDeclaration != null) {
|
|
1790
|
-
// for cases where there is a merged declaration, TS enforces BOTH are exported
|
|
1791
1621
|
return [mainExport, {
|
|
1792
1622
|
type: 'ExportNamedDeclaration',
|
|
1793
1623
|
loc: DUMMY_LOC,
|
|
@@ -1808,7 +1638,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1808
1638
|
loc: DUMMY_LOC,
|
|
1809
1639
|
exported: transform.Identifier(node.exported, false),
|
|
1810
1640
|
local: transform.Identifier(node.local, false),
|
|
1811
|
-
// flow does not support inline exportKind for named exports
|
|
1812
1641
|
exportKind: 'value'
|
|
1813
1642
|
};
|
|
1814
1643
|
},
|
|
@@ -1950,31 +1779,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1950
1779
|
case '$ObjMapi':
|
|
1951
1780
|
case '$TupleMap':
|
|
1952
1781
|
{
|
|
1953
|
-
/*
|
|
1954
|
-
TODO - I don't think it's possible to make these types work in the generic case.
|
|
1955
|
-
TS has no utility types that allow you to generically mimic this functionality.
|
|
1956
|
-
You really need intimiate knowledge of the user's intent in order to correctly
|
|
1957
|
-
transform the code.
|
|
1958
|
-
For example the simple example for $Call from the flow docs:
|
|
1959
|
-
```
|
|
1960
|
-
type ExtractPropType = <T>({prop: T}) => T;
|
|
1961
|
-
type Obj = {prop: number};
|
|
1962
|
-
type PropType = $Call<ExtractPropType, Obj>;
|
|
1963
|
-
// expected -- typeof PropType === number
|
|
1964
|
-
```
|
|
1965
|
-
The equivalent in TS would be:
|
|
1966
|
-
```
|
|
1967
|
-
type ExtractPropType<T extends { prop: any }> = (arg: T) => T['prop'];
|
|
1968
|
-
type Obj = { prop: number };
|
|
1969
|
-
type PropType = ReturnType<ExtractPropType<Obj>>; // number
|
|
1970
|
-
```
|
|
1971
|
-
*/
|
|
1972
1782
|
return unsupportedAnnotation(node, fullTypeName);
|
|
1973
1783
|
}
|
|
1974
1784
|
|
|
1975
1785
|
case '$ArrayBufferView':
|
|
1976
1786
|
{
|
|
1977
|
-
// `$ArrayBufferView` => `ArrayBufferView`
|
|
1978
1787
|
return {
|
|
1979
1788
|
type: 'TSTypeReference',
|
|
1980
1789
|
loc: DUMMY_LOC,
|
|
@@ -1988,7 +1797,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1988
1797
|
|
|
1989
1798
|
case '$ArrayLike':
|
|
1990
1799
|
{
|
|
1991
|
-
// `$ArrayLike<T>` => `ArrayLike<T>`
|
|
1992
1800
|
return {
|
|
1993
1801
|
type: 'TSTypeReference',
|
|
1994
1802
|
loc: DUMMY_LOC,
|
|
@@ -1997,7 +1805,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
1997
1805
|
loc: DUMMY_LOC,
|
|
1998
1806
|
name: 'ArrayLike'
|
|
1999
1807
|
},
|
|
2000
|
-
|
|
1808
|
+
typeArguments: {
|
|
2001
1809
|
type: 'TSTypeParameterInstantiation',
|
|
2002
1810
|
loc: DUMMY_LOC,
|
|
2003
1811
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2008,7 +1816,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2008
1816
|
case '$Diff':
|
|
2009
1817
|
case '$Rest':
|
|
2010
1818
|
{
|
|
2011
|
-
// `$Diff<A, B>` => `Pick<A, Exclude<keyof A, keyof B>>`
|
|
2012
1819
|
const params = assertHasExactlyNTypeParameters(2);
|
|
2013
1820
|
return {
|
|
2014
1821
|
type: 'TSTypeReference',
|
|
@@ -2018,7 +1825,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2018
1825
|
loc: DUMMY_LOC,
|
|
2019
1826
|
name: 'Pick'
|
|
2020
1827
|
},
|
|
2021
|
-
|
|
1828
|
+
typeArguments: {
|
|
2022
1829
|
type: 'TSTypeParameterInstantiation',
|
|
2023
1830
|
loc: DUMMY_LOC,
|
|
2024
1831
|
params: [params[0], {
|
|
@@ -2029,7 +1836,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2029
1836
|
loc: DUMMY_LOC,
|
|
2030
1837
|
name: 'Exclude'
|
|
2031
1838
|
},
|
|
2032
|
-
|
|
1839
|
+
typeArguments: {
|
|
2033
1840
|
type: 'TSTypeParameterInstantiation',
|
|
2034
1841
|
loc: DUMMY_LOC,
|
|
2035
1842
|
params: [{
|
|
@@ -2052,7 +1859,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2052
1859
|
case '$ElementType':
|
|
2053
1860
|
case '$PropertyType':
|
|
2054
1861
|
{
|
|
2055
|
-
// `$ElementType<T, K>` => `T[K]`
|
|
2056
1862
|
const params = assertHasExactlyNTypeParameters(2);
|
|
2057
1863
|
return {
|
|
2058
1864
|
type: 'TSIndexedAccessType',
|
|
@@ -2064,20 +1870,16 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2064
1870
|
|
|
2065
1871
|
case '$Exact':
|
|
2066
1872
|
{
|
|
2067
|
-
// `$Exact<T>` => `T`
|
|
2068
|
-
// TS has no concept of exact vs inexact types
|
|
2069
1873
|
return assertHasExactlyNTypeParameters(1)[0];
|
|
2070
1874
|
}
|
|
2071
1875
|
|
|
2072
1876
|
case '$Exports':
|
|
2073
1877
|
{
|
|
2074
|
-
// `$Exports<'module'>` => `typeof import('module')`
|
|
2075
1878
|
const moduleName = assertHasExactlyNTypeParameters(1)[0];
|
|
2076
1879
|
|
|
2077
1880
|
if (moduleName.type !== 'TSLiteralType' || moduleName.literal.type !== 'Literal' || typeof moduleName.literal.value !== 'string') {
|
|
2078
1881
|
throw translationError(node, '$Exports must have a string literal argument');
|
|
2079
|
-
}
|
|
2080
|
-
|
|
1882
|
+
}
|
|
2081
1883
|
|
|
2082
1884
|
return {
|
|
2083
1885
|
type: 'TSTypeQuery',
|
|
@@ -2087,14 +1889,15 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2087
1889
|
loc: DUMMY_LOC,
|
|
2088
1890
|
argument: moduleName,
|
|
2089
1891
|
qualifier: null,
|
|
2090
|
-
|
|
1892
|
+
options: null,
|
|
1893
|
+
source: moduleName.literal,
|
|
1894
|
+
typeArguments: null
|
|
2091
1895
|
}
|
|
2092
1896
|
};
|
|
2093
1897
|
}
|
|
2094
1898
|
|
|
2095
1899
|
case '$FlowFixMe':
|
|
2096
1900
|
{
|
|
2097
|
-
// `$FlowFixMe` => `any`
|
|
2098
1901
|
return {
|
|
2099
1902
|
type: 'TSAnyKeyword',
|
|
2100
1903
|
loc: DUMMY_LOC
|
|
@@ -2103,7 +1906,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2103
1906
|
|
|
2104
1907
|
case '$KeyMirror':
|
|
2105
1908
|
{
|
|
2106
|
-
// `$KeyMirror<T>` => `{[K in keyof T]: K}`
|
|
2107
1909
|
return {
|
|
2108
1910
|
type: 'TSMappedType',
|
|
2109
1911
|
loc: DUMMY_LOC,
|
|
@@ -2150,7 +1952,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2150
1952
|
|
|
2151
1953
|
case '$Keys':
|
|
2152
1954
|
{
|
|
2153
|
-
// `$Keys<T>` => `keyof T`
|
|
2154
1955
|
return {
|
|
2155
1956
|
type: 'TSTypeOperator',
|
|
2156
1957
|
loc: DUMMY_LOC,
|
|
@@ -2161,8 +1962,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2161
1962
|
|
|
2162
1963
|
case '$NonMaybeType':
|
|
2163
1964
|
{
|
|
2164
|
-
// `$NonMaybeType<T>` => `NonNullable<T>`
|
|
2165
|
-
// Not a great name because `NonNullable` also excludes `undefined`
|
|
2166
1965
|
return {
|
|
2167
1966
|
type: 'TSTypeReference',
|
|
2168
1967
|
loc: DUMMY_LOC,
|
|
@@ -2171,7 +1970,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2171
1970
|
loc: DUMMY_LOC,
|
|
2172
1971
|
name: 'NonNullable'
|
|
2173
1972
|
},
|
|
2174
|
-
|
|
1973
|
+
typeArguments: {
|
|
2175
1974
|
type: 'TSTypeParameterInstantiation',
|
|
2176
1975
|
loc: DUMMY_LOC,
|
|
2177
1976
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2181,7 +1980,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2181
1980
|
|
|
2182
1981
|
case '$ReadOnly':
|
|
2183
1982
|
{
|
|
2184
|
-
// `$ReadOnly<T>` => `Readonly<T>`
|
|
2185
1983
|
return {
|
|
2186
1984
|
type: 'TSTypeReference',
|
|
2187
1985
|
loc: DUMMY_LOC,
|
|
@@ -2190,7 +1988,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2190
1988
|
loc: DUMMY_LOC,
|
|
2191
1989
|
name: 'Readonly'
|
|
2192
1990
|
},
|
|
2193
|
-
|
|
1991
|
+
typeArguments: {
|
|
2194
1992
|
type: 'TSTypeParameterInstantiation',
|
|
2195
1993
|
loc: DUMMY_LOC,
|
|
2196
1994
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2200,10 +1998,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2200
1998
|
|
|
2201
1999
|
case '$ReadOnlyArray':
|
|
2202
2000
|
{
|
|
2203
|
-
// `$ReadOnlyArray<T>` => `ReadonlyArray<T>`
|
|
2204
|
-
//
|
|
2205
|
-
// we could also do => `readonly T[]`
|
|
2206
|
-
// TODO - maybe a config option?
|
|
2207
2001
|
return {
|
|
2208
2002
|
type: 'TSTypeReference',
|
|
2209
2003
|
loc: DUMMY_LOC,
|
|
@@ -2212,7 +2006,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2212
2006
|
loc: DUMMY_LOC,
|
|
2213
2007
|
name: 'ReadonlyArray'
|
|
2214
2008
|
},
|
|
2215
|
-
|
|
2009
|
+
typeArguments: {
|
|
2216
2010
|
type: 'TSTypeParameterInstantiation',
|
|
2217
2011
|
loc: DUMMY_LOC,
|
|
2218
2012
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2230,7 +2024,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2230
2024
|
loc: DUMMY_LOC,
|
|
2231
2025
|
name: 'ReadonlyMap'
|
|
2232
2026
|
},
|
|
2233
|
-
|
|
2027
|
+
typeArguments: {
|
|
2234
2028
|
type: 'TSTypeParameterInstantiation',
|
|
2235
2029
|
loc: DUMMY_LOC,
|
|
2236
2030
|
params: assertHasExactlyNTypeParameters(2)
|
|
@@ -2248,7 +2042,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2248
2042
|
loc: DUMMY_LOC,
|
|
2249
2043
|
name: 'ReadonlySet'
|
|
2250
2044
|
},
|
|
2251
|
-
|
|
2045
|
+
typeArguments: {
|
|
2252
2046
|
type: 'TSTypeParameterInstantiation',
|
|
2253
2047
|
loc: DUMMY_LOC,
|
|
2254
2048
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2259,7 +2053,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2259
2053
|
case '$Values':
|
|
2260
2054
|
case 'Values':
|
|
2261
2055
|
{
|
|
2262
|
-
// `$Values<T>` / `Values<T>` => `T[keyof T]`
|
|
2263
2056
|
const transformedType = assertHasExactlyNTypeParameters(1)[0];
|
|
2264
2057
|
return {
|
|
2265
2058
|
type: 'TSIndexedAccessType',
|
|
@@ -2276,7 +2069,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2276
2069
|
|
|
2277
2070
|
case 'Class':
|
|
2278
2071
|
{
|
|
2279
|
-
// `Class<T>` => `new (...args: any[]) => T`
|
|
2280
2072
|
const param = assertHasExactlyNTypeParameters(1)[0];
|
|
2281
2073
|
|
|
2282
2074
|
if (param.type !== 'TSTypeReference') {
|
|
@@ -2320,8 +2112,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2320
2112
|
{
|
|
2321
2113
|
var _params$;
|
|
2322
2114
|
|
|
2323
|
-
// `StringPrefix<foo>` => `foo${string}`
|
|
2324
|
-
// `StringPrefix<foo, T>` => `foo${T}`
|
|
2325
2115
|
const params = assertHasTypeParametersInRange(1, 2);
|
|
2326
2116
|
const prefix = params[0];
|
|
2327
2117
|
|
|
@@ -2362,8 +2152,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2362
2152
|
{
|
|
2363
2153
|
var _params$2;
|
|
2364
2154
|
|
|
2365
|
-
// `StringSuffix<foo>` => `${string}foo`
|
|
2366
|
-
// `StringSuffix<foo, T>` => `${T}foo`
|
|
2367
2155
|
const params = assertHasTypeParametersInRange(1, 2);
|
|
2368
2156
|
const suffix = params[0];
|
|
2369
2157
|
|
|
@@ -2399,20 +2187,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2399
2187
|
types: [remainder]
|
|
2400
2188
|
};
|
|
2401
2189
|
}
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2190
|
+
}
|
|
2404
2191
|
|
|
2405
2192
|
const validReactImportOrGlobal = isValidReactImportOrGlobal(baseId);
|
|
2406
2193
|
const hasReactImport = isReactImport(baseId, baseId.name);
|
|
2407
2194
|
|
|
2408
2195
|
if (validReactImportOrGlobal || hasReactImport) {
|
|
2409
2196
|
switch (fullTypeName) {
|
|
2410
|
-
// TODO: In flow this is `ChildrenArray<T> = T | $ReadOnlyArray<ChildrenArray<T>>`.
|
|
2411
|
-
// The recursive nature of it is rarely needed, so we're simplifying this for now
|
|
2412
|
-
// but omitting that aspect. Once we're able to provide utility types for our translations,
|
|
2413
|
-
// we should update this.
|
|
2414
|
-
// React.ChildrenArray<T> -> T | ReadonlyArray<T>
|
|
2415
|
-
// React$ChildrenArray<T> -> T | ReadonlyArray<T>
|
|
2416
2197
|
case 'React.ChildrenArray':
|
|
2417
2198
|
case 'React$ChildrenArray':
|
|
2418
2199
|
{
|
|
@@ -2428,7 +2209,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2428
2209
|
loc: DUMMY_LOC,
|
|
2429
2210
|
name: 'ReadonlyArray'
|
|
2430
2211
|
},
|
|
2431
|
-
|
|
2212
|
+
typeArguments: {
|
|
2432
2213
|
type: 'TSTypeParameterInstantiation',
|
|
2433
2214
|
loc: DUMMY_LOC,
|
|
2434
2215
|
params: [param]
|
|
@@ -2436,8 +2217,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2436
2217
|
}]
|
|
2437
2218
|
};
|
|
2438
2219
|
}
|
|
2439
|
-
// React.Component<A,B> -> React.Component<A,B>
|
|
2440
|
-
// React$Component<A,B> -> React.Component<A,B>
|
|
2441
2220
|
|
|
2442
2221
|
case 'React.Component':
|
|
2443
2222
|
case 'React$Component':
|
|
@@ -2467,15 +2246,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2467
2246
|
name: 'Component'
|
|
2468
2247
|
}
|
|
2469
2248
|
},
|
|
2470
|
-
|
|
2249
|
+
typeArguments: {
|
|
2471
2250
|
type: 'TSTypeParameterInstantiation',
|
|
2472
2251
|
loc: DUMMY_LOC,
|
|
2473
2252
|
params: params.map(param => transformTypeAnnotationType(param))
|
|
2474
2253
|
}
|
|
2475
2254
|
};
|
|
2476
2255
|
}
|
|
2477
|
-
// React.Context<A> -> React.Context<A>
|
|
2478
|
-
// React$Context<A> -> React.Context<A>
|
|
2479
2256
|
|
|
2480
2257
|
case 'React$Context':
|
|
2481
2258
|
case 'React.Context':
|
|
@@ -2492,14 +2269,12 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2492
2269
|
name: `Context`
|
|
2493
2270
|
}
|
|
2494
2271
|
},
|
|
2495
|
-
|
|
2272
|
+
typeArguments: {
|
|
2496
2273
|
type: 'TSTypeParameterInstantiation',
|
|
2497
2274
|
loc: DUMMY_LOC,
|
|
2498
2275
|
params: assertHasExactlyNTypeParameters(1)
|
|
2499
2276
|
}
|
|
2500
2277
|
};
|
|
2501
|
-
// React.Key -> React.Key
|
|
2502
|
-
// React$Key -> React.Key
|
|
2503
2278
|
|
|
2504
2279
|
case 'React.Key':
|
|
2505
2280
|
case 'React$Key':
|
|
@@ -2518,8 +2293,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2518
2293
|
}
|
|
2519
2294
|
}
|
|
2520
2295
|
};
|
|
2521
|
-
// React.ElementType -> React.ElementType
|
|
2522
|
-
// React$ElementType -> React.ElementType
|
|
2523
2296
|
|
|
2524
2297
|
case 'React$ElementType':
|
|
2525
2298
|
case 'React.ElementType':
|
|
@@ -2538,10 +2311,9 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2538
2311
|
name: `ElementType`
|
|
2539
2312
|
}
|
|
2540
2313
|
},
|
|
2541
|
-
|
|
2314
|
+
typeArguments: undefined
|
|
2542
2315
|
};
|
|
2543
2316
|
}
|
|
2544
|
-
// React.Node -> React.ReactNode
|
|
2545
2317
|
|
|
2546
2318
|
case 'React$Node':
|
|
2547
2319
|
case 'React.Node':
|
|
@@ -2560,10 +2332,9 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2560
2332
|
name: `ReactNode`
|
|
2561
2333
|
}
|
|
2562
2334
|
},
|
|
2563
|
-
|
|
2335
|
+
typeArguments: undefined
|
|
2564
2336
|
};
|
|
2565
2337
|
}
|
|
2566
|
-
// React.Element<typeof Component> -> React.ReactElement<typeof Component>
|
|
2567
2338
|
|
|
2568
2339
|
case 'React$Element':
|
|
2569
2340
|
case 'React.Element':
|
|
@@ -2581,15 +2352,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2581
2352
|
name: `ReactElement`
|
|
2582
2353
|
}
|
|
2583
2354
|
},
|
|
2584
|
-
|
|
2355
|
+
typeArguments: {
|
|
2585
2356
|
type: 'TSTypeParameterInstantiation',
|
|
2586
2357
|
loc: DUMMY_LOC,
|
|
2587
2358
|
params: assertHasExactlyNTypeParameters(1)
|
|
2588
2359
|
}
|
|
2589
2360
|
};
|
|
2590
2361
|
}
|
|
2591
|
-
// React.ElementRef<typeof Component> -> React.ComponentRef<typeof Component>
|
|
2592
|
-
// React$ElementRef<typeof Component> -> React.ComponentRef<typeof Component>
|
|
2593
2362
|
|
|
2594
2363
|
case 'React$ElementRef':
|
|
2595
2364
|
case 'React.ElementRef':
|
|
@@ -2606,14 +2375,12 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2606
2375
|
name: `ComponentRef`
|
|
2607
2376
|
}
|
|
2608
2377
|
},
|
|
2609
|
-
|
|
2378
|
+
typeArguments: {
|
|
2610
2379
|
type: 'TSTypeParameterInstantiation',
|
|
2611
2380
|
loc: DUMMY_LOC,
|
|
2612
2381
|
params: assertHasExactlyNTypeParameters(1)
|
|
2613
2382
|
}
|
|
2614
2383
|
};
|
|
2615
|
-
// React$Fragment -> React.Fragment
|
|
2616
|
-
// React.Fragment -> React.Fragment
|
|
2617
2384
|
|
|
2618
2385
|
case 'React$FragmentType':
|
|
2619
2386
|
case 'React.Fragment':
|
|
@@ -2632,7 +2399,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2632
2399
|
}
|
|
2633
2400
|
}
|
|
2634
2401
|
};
|
|
2635
|
-
// React.MixedElement -> React.JSX.Element
|
|
2636
2402
|
|
|
2637
2403
|
case 'React$MixedElement':
|
|
2638
2404
|
case 'React.MixedElement':
|
|
@@ -2664,11 +2430,9 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2664
2430
|
name: 'Element'
|
|
2665
2431
|
}
|
|
2666
2432
|
},
|
|
2667
|
-
|
|
2433
|
+
typeArguments: undefined
|
|
2668
2434
|
};
|
|
2669
2435
|
}
|
|
2670
|
-
// React.ComponentType<Config> -> React.ComponentType<Config>
|
|
2671
|
-
// React$ComponentType<Config> -> React.ComponentType<Config>
|
|
2672
2436
|
|
|
2673
2437
|
case 'React.ComponentType':
|
|
2674
2438
|
case 'React$ComponentType':
|
|
@@ -2686,17 +2450,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2686
2450
|
name: 'ComponentType'
|
|
2687
2451
|
}
|
|
2688
2452
|
},
|
|
2689
|
-
|
|
2453
|
+
typeArguments: {
|
|
2690
2454
|
type: 'TSTypeParameterInstantiation',
|
|
2691
2455
|
loc: DUMMY_LOC,
|
|
2692
2456
|
params: assertHasExactlyNTypeParameters(1)
|
|
2693
2457
|
}
|
|
2694
2458
|
};
|
|
2695
2459
|
}
|
|
2696
|
-
// React.AbstractComponent<Config> -> React.ComponentType<Config>
|
|
2697
|
-
// React$AbstractComponent<Config> -> React.ComponentType<Config>
|
|
2698
|
-
// React.AbstractComponent<Config, Instance> -> React.ComponentType<Config & React.RefAttributes<Instance>>
|
|
2699
|
-
// React$AbstractComponent<Config, Instance> -> React.ComponentType<Config & React.RefAttributes<Instance>>
|
|
2700
2460
|
|
|
2701
2461
|
case 'React.AbstractComponent':
|
|
2702
2462
|
case 'React$AbstractComponent':
|
|
@@ -2740,7 +2500,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2740
2500
|
name: 'RefAttributes'
|
|
2741
2501
|
}
|
|
2742
2502
|
},
|
|
2743
|
-
|
|
2503
|
+
typeArguments: {
|
|
2744
2504
|
type: 'TSTypeParameterInstantiation',
|
|
2745
2505
|
loc: DUMMY_LOC,
|
|
2746
2506
|
params: [ref]
|
|
@@ -2762,15 +2522,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2762
2522
|
name: 'ComponentType'
|
|
2763
2523
|
}
|
|
2764
2524
|
},
|
|
2765
|
-
|
|
2525
|
+
typeArguments: {
|
|
2766
2526
|
type: 'TSTypeParameterInstantiation',
|
|
2767
2527
|
loc: DUMMY_LOC,
|
|
2768
2528
|
params: newParams
|
|
2769
2529
|
}
|
|
2770
2530
|
};
|
|
2771
2531
|
}
|
|
2772
|
-
// React.ElementProps<A> -> React.ComponentProps<A>
|
|
2773
|
-
// React$ElementProps<A> -> React.ComponentProps<A>
|
|
2774
2532
|
|
|
2775
2533
|
case 'React.ElementProps':
|
|
2776
2534
|
case 'React$ElementProps':
|
|
@@ -2788,15 +2546,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2788
2546
|
name: 'ComponentProps'
|
|
2789
2547
|
}
|
|
2790
2548
|
},
|
|
2791
|
-
|
|
2549
|
+
typeArguments: {
|
|
2792
2550
|
type: 'TSTypeParameterInstantiation',
|
|
2793
2551
|
loc: DUMMY_LOC,
|
|
2794
2552
|
params: assertHasExactlyNTypeParameters(1)
|
|
2795
2553
|
}
|
|
2796
2554
|
};
|
|
2797
2555
|
}
|
|
2798
|
-
// React.ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
|
|
2799
|
-
// React$ElementConfig<A> -> React.JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
|
|
2800
2556
|
|
|
2801
2557
|
case 'React.ElementConfig':
|
|
2802
2558
|
case 'React$ElementConfig':
|
|
@@ -2828,7 +2584,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2828
2584
|
name: 'LibraryManagedAttributes'
|
|
2829
2585
|
}
|
|
2830
2586
|
},
|
|
2831
|
-
|
|
2587
|
+
typeArguments: {
|
|
2832
2588
|
type: 'TSTypeParameterInstantiation',
|
|
2833
2589
|
loc: DUMMY_LOC,
|
|
2834
2590
|
params: [param, {
|
|
@@ -2844,7 +2600,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2844
2600
|
name: `ComponentProps`
|
|
2845
2601
|
}
|
|
2846
2602
|
},
|
|
2847
|
-
|
|
2603
|
+
typeArguments: {
|
|
2848
2604
|
type: 'TSTypeParameterInstantiation',
|
|
2849
2605
|
loc: DUMMY_LOC,
|
|
2850
2606
|
params: [param]
|
|
@@ -2853,8 +2609,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2853
2609
|
}
|
|
2854
2610
|
};
|
|
2855
2611
|
}
|
|
2856
|
-
// React.RefSetter<C> -> React.Ref<C>
|
|
2857
|
-
// React$RefSetter<C> -> React.Ref<C>
|
|
2858
2612
|
|
|
2859
2613
|
case 'React.RefSetter':
|
|
2860
2614
|
case 'React$RefSetter':
|
|
@@ -2871,7 +2625,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2871
2625
|
name: 'Ref'
|
|
2872
2626
|
}
|
|
2873
2627
|
},
|
|
2874
|
-
|
|
2628
|
+
typeArguments: {
|
|
2875
2629
|
type: 'TSTypeParameterInstantiation',
|
|
2876
2630
|
loc: DUMMY_LOC,
|
|
2877
2631
|
params: assertHasExactlyNTypeParameters(1)
|
|
@@ -2887,7 +2641,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2887
2641
|
type: 'TSTypeReference',
|
|
2888
2642
|
loc: DUMMY_LOC,
|
|
2889
2643
|
typeName: node.id.type === 'Identifier' ? transform.Identifier(node.id, false) : transform.QualifiedTypeIdentifier(node.id),
|
|
2890
|
-
|
|
2644
|
+
typeArguments: transform.TypeParameterInstantiation(node.typeParameters)
|
|
2891
2645
|
};
|
|
2892
2646
|
},
|
|
2893
2647
|
|
|
@@ -2996,24 +2750,20 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
2996
2750
|
type: 'TSInterfaceHeritage',
|
|
2997
2751
|
loc: DUMMY_LOC,
|
|
2998
2752
|
expression: node.id.type === 'QualifiedTypeIdentifier' ? transform.QualifiedTypeIdentifier(node.id) : transform.Identifier(node.id, false),
|
|
2999
|
-
|
|
2753
|
+
typeArguments: transform.TypeParameterInstantiation(node.typeParameters)
|
|
3000
2754
|
};
|
|
3001
2755
|
},
|
|
3002
2756
|
|
|
3003
2757
|
InterfaceTypeAnnotation(node) {
|
|
3004
2758
|
if (node.extends) {
|
|
3005
|
-
// type T = interface extends U, V { ... }
|
|
3006
|
-
// to
|
|
3007
|
-
// type T = U & V & { ... }
|
|
3008
2759
|
return {
|
|
3009
2760
|
type: 'TSIntersectionType',
|
|
3010
2761
|
loc: DUMMY_LOC,
|
|
3011
2762
|
types: [...node.extends.map(ex => ({
|
|
3012
2763
|
type: 'TSTypeReference',
|
|
3013
2764
|
loc: DUMMY_LOC,
|
|
3014
|
-
// Bug: ex.id can be qualified
|
|
3015
2765
|
typeName: transform.Identifier(ex.id, false),
|
|
3016
|
-
|
|
2766
|
+
typeArguments: transform.TypeParameterInstantiation(ex.typeParameters)
|
|
3017
2767
|
})), transform.ObjectTypeAnnotation(node.body)]
|
|
3018
2768
|
};
|
|
3019
2769
|
}
|
|
@@ -3075,8 +2825,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3075
2825
|
},
|
|
3076
2826
|
|
|
3077
2827
|
NullableTypeAnnotation(node) {
|
|
3078
|
-
// TS doesn't support the maybe type, so have to explicitly union in `null | undefined`
|
|
3079
|
-
// `?T` becomes `null | undefined | T`
|
|
3080
2828
|
return {
|
|
3081
2829
|
type: 'TSUnionType',
|
|
3082
2830
|
loc: DUMMY_LOC,
|
|
@@ -3123,7 +2871,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3123
2871
|
if (node.properties.length === 1 && node.properties[0].type === 'ObjectTypeMappedTypeProperty') {
|
|
3124
2872
|
var _prop$variance, _prop$variance2;
|
|
3125
2873
|
|
|
3126
|
-
// Mapped Object Object types must not have other object properties.
|
|
3127
2874
|
const prop = node.properties[0];
|
|
3128
2875
|
const tsProp = {
|
|
3129
2876
|
type: 'TSMappedType',
|
|
@@ -3152,11 +2899,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3152
2899
|
nameType: null
|
|
3153
2900
|
};
|
|
3154
2901
|
return tsProp;
|
|
3155
|
-
}
|
|
3156
|
-
// unfortunately flow has unordered properties storing things
|
|
3157
|
-
// so store all elements with their start index and sort the
|
|
3158
|
-
// list afterward
|
|
3159
|
-
|
|
2902
|
+
}
|
|
3160
2903
|
|
|
3161
2904
|
const members = [];
|
|
3162
2905
|
|
|
@@ -3173,12 +2916,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3173
2916
|
node: transform.ObjectTypeIndexer(indexer)
|
|
3174
2917
|
});
|
|
3175
2918
|
}
|
|
3176
|
-
/*
|
|
3177
|
-
TODO - internalSlots
|
|
3178
|
-
I don't think there's anything analogous in TS.
|
|
3179
|
-
They're really rarely used (if ever) - so let's just ignore them for now
|
|
3180
|
-
*/
|
|
3181
|
-
|
|
3182
2919
|
|
|
3183
2920
|
if (node.internalSlots.length > 0) {
|
|
3184
2921
|
return unsupportedAnnotation(node.internalSlots[0], 'internal slots');
|
|
@@ -3187,8 +2924,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3187
2924
|
if (!node.properties.find(FlowESTree.isObjectTypeSpreadProperty)) {
|
|
3188
2925
|
for (const property of node.properties) {
|
|
3189
2926
|
if (property.type === 'ObjectTypeSpreadProperty') {
|
|
3190
|
-
// this is imposible due to the above find condition
|
|
3191
|
-
// this check is purely to satisfy flow
|
|
3192
2927
|
throw unexpectedTranslationError(property, 'Impossible state');
|
|
3193
2928
|
}
|
|
3194
2929
|
|
|
@@ -3211,67 +2946,8 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3211
2946
|
members: tsBody
|
|
3212
2947
|
};
|
|
3213
2948
|
} else {
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
in flow type spreads are modelled after object spreads; meaning that for
|
|
3217
|
-
{ ...A, ...B } - all properties in B will explicitly replace any properties
|
|
3218
|
-
in A of the same name.
|
|
3219
|
-
```
|
|
3220
|
-
type T1 = { a: string };
|
|
3221
|
-
type T2 = { a: number };
|
|
3222
|
-
type T3 = { ...T1, ...T2 };
|
|
3223
|
-
type A = T3['a'] // === number
|
|
3224
|
-
```
|
|
3225
|
-
however in TS there are no object type spreads - you can only merge
|
|
3226
|
-
objects either via the intersection operator or via interface extends.
|
|
3227
|
-
For an interface extends - `interface B extends A { ... }` - TS enforces
|
|
3228
|
-
that the properties of B are all covariantly related to the same named
|
|
3229
|
-
properties in A.
|
|
3230
|
-
So we can't use an interface extends.
|
|
3231
|
-
For a type intersection - `type T = A & B;` - TS will (essentially) merge
|
|
3232
|
-
the types by intersecting each same named property in each type to calculate
|
|
3233
|
-
the resulting type. This has the effect of enforcing the same constraint
|
|
3234
|
-
as the interface case, however instead of an error it causes properties to
|
|
3235
|
-
become `never`:
|
|
3236
|
-
```
|
|
3237
|
-
type T1 = { a: string };
|
|
3238
|
-
type T2 = { a: number };
|
|
3239
|
-
type T3 = T1 & T2;
|
|
3240
|
-
type A = T3['a'] // === string & number === never
|
|
3241
|
-
```
|
|
3242
|
-
So in order for us to model flow's spreads we have to explicitly omit the keys
|
|
3243
|
-
from the proceeding type that might clash. We can do this pretty easily using
|
|
3244
|
-
TS's utility types:
|
|
3245
|
-
```
|
|
3246
|
-
type T1 = { a: string };
|
|
3247
|
-
type T2 = { a: number };
|
|
3248
|
-
type T3 = Omit<T1, keyof T2> & T2;
|
|
3249
|
-
type A = T3['a'] // === number
|
|
3250
|
-
```
|
|
3251
|
-
Unfortunately because we need to solve for the general case object type usage,
|
|
3252
|
-
it's going to be a bit ugly and complicated, sadly.
|
|
3253
|
-
If we had access to type information we would be able to skip some ugliness by
|
|
3254
|
-
checking to see if there is any overlap and skipping the omit step if there isn't.
|
|
3255
|
-
But alas - we're working purely syntactically.
|
|
3256
|
-
```
|
|
3257
|
-
type T = { ...T1, b: string };
|
|
3258
|
-
// becomes
|
|
3259
|
-
type T = Omit<T1, keyof { b: string }> & { b: string };
|
|
3260
|
-
```
|
|
3261
|
-
```
|
|
3262
|
-
type T = { ...T1, ...T2, ...T3, b: string };
|
|
3263
|
-
// becomes
|
|
3264
|
-
type T =
|
|
3265
|
-
& Omit<T1, keyof T2 | keyof T3 | keyof { b: string }>
|
|
3266
|
-
& Omit<T2, keyof T3 | keyof { b: string }>
|
|
3267
|
-
& Omit<T3, keyof { b: string }>
|
|
3268
|
-
& { b: string };
|
|
3269
|
-
```
|
|
3270
|
-
Note that because it's going to be super ugly and complicated - for now we're going to disallow:
|
|
3271
|
-
- spreads in the middle
|
|
3272
|
-
- spreads at the end
|
|
3273
|
-
- spreads of things that aren't "Identifiers"
|
|
3274
|
-
*/
|
|
2949
|
+
var _extractPropertyKeyLi;
|
|
2950
|
+
|
|
3275
2951
|
if (members.length > 0) {
|
|
3276
2952
|
return unsupportedAnnotation(node, 'object types with spreads, indexers and/or call properties at the same time');
|
|
3277
2953
|
}
|
|
@@ -3292,7 +2968,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3292
2968
|
|
|
3293
2969
|
typesToIntersect.push(spreadType);
|
|
3294
2970
|
} else if (property.type === 'ObjectTypeMappedTypeProperty') {
|
|
3295
|
-
// TODO - Support mapped types
|
|
3296
2971
|
return unsupportedAnnotation(property, 'object type with mapped type property');
|
|
3297
2972
|
} else {
|
|
3298
2973
|
members.push({
|
|
@@ -3310,11 +2985,23 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3310
2985
|
loc: DUMMY_LOC,
|
|
3311
2986
|
members: tsBody
|
|
3312
2987
|
};
|
|
2988
|
+
const objectKeyTypes = (_extractPropertyKeyLi = (0, _TSNodeUtils.extractPropertyKeyLiterals)(tsBody)) != null ? _extractPropertyKeyLi : [{
|
|
2989
|
+
type: 'TSTypeOperator',
|
|
2990
|
+
loc: DUMMY_LOC,
|
|
2991
|
+
operator: 'keyof',
|
|
2992
|
+
typeAnnotation: objectType
|
|
2993
|
+
}];
|
|
3313
2994
|
const intersectionMembers = [];
|
|
3314
2995
|
|
|
3315
2996
|
for (let i = 0; i < typesToIntersect.length; i += 1) {
|
|
3316
2997
|
const currentType = typesToIntersect[i];
|
|
3317
2998
|
const remainingTypes = typesToIntersect.slice(i + 1);
|
|
2999
|
+
const omitKeyTypes = [...remainingTypes.map(t => ({
|
|
3000
|
+
type: 'TSTypeOperator',
|
|
3001
|
+
loc: DUMMY_LOC,
|
|
3002
|
+
operator: 'keyof',
|
|
3003
|
+
typeAnnotation: t
|
|
3004
|
+
})), ...objectKeyTypes];
|
|
3318
3005
|
intersectionMembers.push({
|
|
3319
3006
|
type: 'TSTypeReference',
|
|
3320
3007
|
loc: DUMMY_LOC,
|
|
@@ -3323,23 +3010,13 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3323
3010
|
loc: DUMMY_LOC,
|
|
3324
3011
|
name: 'Omit'
|
|
3325
3012
|
},
|
|
3326
|
-
|
|
3013
|
+
typeArguments: {
|
|
3327
3014
|
type: 'TSTypeParameterInstantiation',
|
|
3328
3015
|
loc: DUMMY_LOC,
|
|
3329
|
-
params: [currentType, {
|
|
3016
|
+
params: [currentType, omitKeyTypes.length === 1 ? omitKeyTypes[0] : {
|
|
3330
3017
|
type: 'TSUnionType',
|
|
3331
3018
|
loc: DUMMY_LOC,
|
|
3332
|
-
types:
|
|
3333
|
-
type: 'TSTypeOperator',
|
|
3334
|
-
loc: DUMMY_LOC,
|
|
3335
|
-
operator: 'keyof',
|
|
3336
|
-
typeAnnotation: t
|
|
3337
|
-
})), {
|
|
3338
|
-
type: 'TSTypeOperator',
|
|
3339
|
-
loc: DUMMY_LOC,
|
|
3340
|
-
operator: 'keyof',
|
|
3341
|
-
typeAnnotation: objectType
|
|
3342
|
-
}]
|
|
3019
|
+
types: omitKeyTypes
|
|
3343
3020
|
}]
|
|
3344
3021
|
}
|
|
3345
3022
|
});
|
|
@@ -3355,7 +3032,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3355
3032
|
},
|
|
3356
3033
|
|
|
3357
3034
|
ObjectTypeCallProperty(node) {
|
|
3358
|
-
// the info is stored on the "value"
|
|
3359
3035
|
const func = transform.FunctionTypeAnnotation(node.value);
|
|
3360
3036
|
return {
|
|
3361
3037
|
type: 'TSCallSignatureDeclaration',
|
|
@@ -3464,10 +3140,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3464
3140
|
})();
|
|
3465
3141
|
|
|
3466
3142
|
if (node.method === true) {
|
|
3467
|
-
|
|
3468
|
-
// TS has separate nodes for methods and properties
|
|
3469
|
-
const func = transform.FunctionTypeAnnotation(node.value); // $FlowFixMe[incompatible-type] `computed` is set dynamically
|
|
3470
|
-
|
|
3143
|
+
const func = transform.FunctionTypeAnnotation(node.value);
|
|
3471
3144
|
return {
|
|
3472
3145
|
type: 'TSMethodSignature',
|
|
3473
3146
|
loc: DUMMY_LOC,
|
|
@@ -3483,10 +3156,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3483
3156
|
}
|
|
3484
3157
|
|
|
3485
3158
|
if (node.kind === 'get' || node.kind === 'set') {
|
|
3486
|
-
|
|
3487
|
-
// TS treats them as method signatures
|
|
3488
|
-
const func = transform.FunctionTypeAnnotation(node.value); // $FlowFixMe[incompatible-type] `computed` is set dynamically
|
|
3489
|
-
|
|
3159
|
+
const func = transform.FunctionTypeAnnotation(node.value);
|
|
3490
3160
|
return {
|
|
3491
3161
|
type: 'TSMethodSignature',
|
|
3492
3162
|
loc: DUMMY_LOC,
|
|
@@ -3495,14 +3165,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3495
3165
|
kind: node.kind,
|
|
3496
3166
|
optional: false,
|
|
3497
3167
|
params: func.params,
|
|
3498
|
-
// TS setters must not have a return type
|
|
3499
3168
|
returnType: node.kind === 'set' ? undefined : func.returnType,
|
|
3500
3169
|
static: node.static,
|
|
3501
|
-
// TS accessors cannot have type parameters
|
|
3502
3170
|
typeParameters: undefined
|
|
3503
3171
|
};
|
|
3504
|
-
}
|
|
3505
|
-
|
|
3172
|
+
}
|
|
3506
3173
|
|
|
3507
3174
|
return {
|
|
3508
3175
|
type: 'TSPropertySignature',
|
|
@@ -3525,14 +3192,9 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3525
3192
|
},
|
|
3526
3193
|
|
|
3527
3194
|
OptionalIndexedAccessType(node) {
|
|
3528
|
-
// Foo?.[A][B]
|
|
3529
|
-
// ^^^^^^^^ optional = true
|
|
3530
|
-
// ^^^^^^^^^^^ optional = false
|
|
3531
3195
|
if (node.optional === false) {
|
|
3532
3196
|
return transform.IndexedAccessType(node);
|
|
3533
|
-
}
|
|
3534
|
-
// `T?.[K]` becomes `NonNullable<T>[K]`
|
|
3535
|
-
|
|
3197
|
+
}
|
|
3536
3198
|
|
|
3537
3199
|
return {
|
|
3538
3200
|
type: 'TSIndexedAccessType',
|
|
@@ -3545,7 +3207,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3545
3207
|
loc: DUMMY_LOC,
|
|
3546
3208
|
name: 'NonNullable'
|
|
3547
3209
|
},
|
|
3548
|
-
|
|
3210
|
+
typeArguments: {
|
|
3549
3211
|
type: 'TSTypeParameterInstantiation',
|
|
3550
3212
|
loc: DUMMY_LOC,
|
|
3551
3213
|
params: [transformTypeAnnotationType(node.objectType)]
|
|
@@ -3712,7 +3374,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3712
3374
|
type: 'TSTypeQuery',
|
|
3713
3375
|
loc: DUMMY_LOC,
|
|
3714
3376
|
exprName: transform.Identifier(node.argument),
|
|
3715
|
-
|
|
3377
|
+
typeArguments: undefined
|
|
3716
3378
|
};
|
|
3717
3379
|
|
|
3718
3380
|
case 'QualifiedTypeofIdentifier':
|
|
@@ -3720,31 +3382,12 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3720
3382
|
type: 'TSTypeQuery',
|
|
3721
3383
|
loc: DUMMY_LOC,
|
|
3722
3384
|
exprName: transform.QualifiedTypeofIdentifier(node.argument),
|
|
3723
|
-
|
|
3385
|
+
typeArguments: undefined
|
|
3724
3386
|
};
|
|
3725
3387
|
}
|
|
3726
3388
|
},
|
|
3727
3389
|
|
|
3728
3390
|
TypeParameter(node) {
|
|
3729
|
-
/*
|
|
3730
|
-
TODO - flow models variance as explicit syntax, but but TS resolves it automatically
|
|
3731
|
-
TS does have syntax for explicit variance, but you can introduce a TS error if the
|
|
3732
|
-
marked parameter isn't used in the location that TS expects them to be in.
|
|
3733
|
-
To make it easier for now let's just rely on TS's auto-resolution.
|
|
3734
|
-
```
|
|
3735
|
-
const variance =
|
|
3736
|
-
new Set(
|
|
3737
|
-
node.variance == null
|
|
3738
|
-
? // by default flow generics act invariantly
|
|
3739
|
-
['in', 'out']
|
|
3740
|
-
: node.variance.kind === 'plus'
|
|
3741
|
-
? // covariant
|
|
3742
|
-
['out']
|
|
3743
|
-
: // contravariant
|
|
3744
|
-
['in'],
|
|
3745
|
-
);
|
|
3746
|
-
```
|
|
3747
|
-
*/
|
|
3748
3391
|
return {
|
|
3749
3392
|
type: 'TSTypeParameter',
|
|
3750
3393
|
loc: DUMMY_LOC,
|
|
@@ -3756,9 +3399,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3756
3399
|
constraint: node.bound == null ? undefined : transformTypeAnnotationType(node.bound.typeAnnotation),
|
|
3757
3400
|
default: node.default == null ? undefined : transformTypeAnnotationType(node.default),
|
|
3758
3401
|
in: false,
|
|
3759
|
-
out: false
|
|
3760
|
-
// out: variance.has('out'),
|
|
3761
|
-
|
|
3402
|
+
out: false
|
|
3762
3403
|
};
|
|
3763
3404
|
},
|
|
3764
3405
|
|
|
@@ -3771,8 +3412,6 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3771
3412
|
},
|
|
3772
3413
|
|
|
3773
3414
|
TypeParameterInstantiation(node) {
|
|
3774
|
-
// Empty parameters in Flow are valid, but TS requires at least one parameter.
|
|
3775
|
-
// This ensures empty type parameters are not created in TS
|
|
3776
3415
|
if (node == null || node.params.length === 0) {
|
|
3777
3416
|
return undefined;
|
|
3778
3417
|
}
|
|
@@ -3882,7 +3521,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3882
3521
|
name: `ReactNode`
|
|
3883
3522
|
}
|
|
3884
3523
|
},
|
|
3885
|
-
|
|
3524
|
+
typeArguments: undefined
|
|
3886
3525
|
};
|
|
3887
3526
|
}
|
|
3888
3527
|
}
|
|
@@ -3890,13 +3529,11 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3890
3529
|
|
|
3891
3530
|
ComponentTypeAnnotation(node) {
|
|
3892
3531
|
const typeParameters = node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters);
|
|
3893
|
-
const params = transform.ComponentTypeParameters(node.params, node.rest);
|
|
3894
|
-
|
|
3532
|
+
const params = transform.ComponentTypeParameters(node.params, node.rest);
|
|
3895
3533
|
const hasReactImport = isReactImport(node, 'React');
|
|
3896
3534
|
const returnType = {
|
|
3897
3535
|
type: 'TSTypeAnnotation',
|
|
3898
3536
|
loc: DUMMY_LOC,
|
|
3899
|
-
// If no rendersType we assume its ReactNode type.
|
|
3900
3537
|
typeAnnotation: {
|
|
3901
3538
|
type: 'TSTypeReference',
|
|
3902
3539
|
loc: DUMMY_LOC,
|
|
@@ -3910,7 +3547,7 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3910
3547
|
name: `ReactNode`
|
|
3911
3548
|
}
|
|
3912
3549
|
},
|
|
3913
|
-
|
|
3550
|
+
typeArguments: undefined
|
|
3914
3551
|
}
|
|
3915
3552
|
};
|
|
3916
3553
|
return {
|
|
@@ -3922,12 +3559,10 @@ const getTransforms = (originalCode, scopeManager, opts) => {
|
|
|
3922
3559
|
};
|
|
3923
3560
|
}
|
|
3924
3561
|
|
|
3925
|
-
};
|
|
3926
|
-
// this just saves us manually wiring up every single case
|
|
3562
|
+
};
|
|
3927
3563
|
|
|
3928
3564
|
for (const key of Object.keys(transform)) {
|
|
3929
|
-
const originalFn = transform[key];
|
|
3930
|
-
// $FlowExpectedError[missing-local-annot]
|
|
3565
|
+
const originalFn = transform[key];
|
|
3931
3566
|
|
|
3932
3567
|
transform[key] = (node, ...args) => {
|
|
3933
3568
|
const result = originalFn(node, ...args);
|