flow-api-translator 0.10.1 → 0.11.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/flowDefToTSDef.js +941 -564
- package/dist/flowDefToTSDef.js.flow +1065 -609
- package/dist/flowToFlowDef.js +2 -1
- package/dist/flowToFlowDef.js.flow +1 -0
- package/dist/index.js +4 -2
- package/dist/index.js.flow +4 -2
- package/dist/utils/ErrorUtils.js +3 -2
- package/dist/utils/ErrorUtils.js.flow +5 -4
- package/package.json +1 -1
package/dist/flowDefToTSDef.js
CHANGED
|
@@ -24,15 +24,25 @@ var _ErrorUtils = require("./utils/ErrorUtils");
|
|
|
24
24
|
|
|
25
25
|
var _DocblockUtils = require("./utils/DocblockUtils");
|
|
26
26
|
|
|
27
|
+
var _os = require("os");
|
|
28
|
+
|
|
27
29
|
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); }
|
|
28
30
|
|
|
29
31
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
30
32
|
|
|
31
33
|
const cloneJSDocCommentsToNewNode = // $FlowExpectedError[incompatible-cast] - trust me this re-type is 100% safe
|
|
32
34
|
_hermesTransform.cloneJSDocCommentsToNewNode;
|
|
35
|
+
const makeCommentOwnLine = // $FlowExpectedError[incompatible-cast] - trust me this re-type is 100% safe
|
|
36
|
+
_hermesTransform.makeCommentOwnLine;
|
|
33
37
|
const VALID_REACT_IMPORTS = new Set(['React', 'react']);
|
|
34
38
|
|
|
35
|
-
function
|
|
39
|
+
function isValidReactImportOrGlobal(id) {
|
|
40
|
+
return VALID_REACT_IMPORTS.has(id.name) || id.name.startsWith('React$');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let shouldAddReactImport = null;
|
|
44
|
+
|
|
45
|
+
function flowDefToTSDef(originalCode, ast, scopeManager, opts) {
|
|
36
46
|
const tsBody = [];
|
|
37
47
|
const tsProgram = {
|
|
38
48
|
type: 'Program',
|
|
@@ -40,7 +50,8 @@ function flowDefToTSDef(originalCode, ast, scopeManager) {
|
|
|
40
50
|
sourceType: ast.sourceType,
|
|
41
51
|
docblock: ast.docblock == null ? null : (0, _DocblockUtils.removeAtFlowFromDocblock)(ast.docblock)
|
|
42
52
|
};
|
|
43
|
-
|
|
53
|
+
shouldAddReactImport = null;
|
|
54
|
+
const [transform, code] = getTransforms(originalCode, scopeManager, opts);
|
|
44
55
|
|
|
45
56
|
for (const node of ast.body) {
|
|
46
57
|
if (node.type in transform) {
|
|
@@ -51,15 +62,37 @@ function flowDefToTSDef(originalCode, ast, scopeManager) {
|
|
|
51
62
|
tsBody.push(...(Array.isArray(result) ? result : [result]));
|
|
52
63
|
} else {
|
|
53
64
|
throw (0, _ErrorUtils.unexpectedTranslationError)(node, `Unexpected node type ${node.type}`, {
|
|
54
|
-
code
|
|
65
|
+
code
|
|
55
66
|
});
|
|
56
67
|
}
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
if (shouldAddReactImport === true) {
|
|
71
|
+
tsBody.unshift({
|
|
72
|
+
type: 'ImportDeclaration',
|
|
73
|
+
assertions: [],
|
|
74
|
+
source: {
|
|
75
|
+
type: 'Literal',
|
|
76
|
+
value: 'react',
|
|
77
|
+
raw: "'react'"
|
|
78
|
+
},
|
|
79
|
+
specifiers: [{
|
|
80
|
+
type: 'ImportNamespaceSpecifier',
|
|
81
|
+
local: {
|
|
82
|
+
type: 'Identifier',
|
|
83
|
+
name: 'React'
|
|
84
|
+
}
|
|
85
|
+
}],
|
|
86
|
+
importKind: 'value'
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return [tsProgram, code];
|
|
60
91
|
}
|
|
61
92
|
|
|
62
|
-
const getTransforms = (
|
|
93
|
+
const getTransforms = (originalCode, scopeManager, opts) => {
|
|
94
|
+
let code = originalCode;
|
|
95
|
+
|
|
63
96
|
function translationError(node, message) {
|
|
64
97
|
return (0, _ErrorUtils.translationError)(node, message, {
|
|
65
98
|
code
|
|
@@ -72,8 +105,66 @@ const getTransforms = (code, scopeManager) => {
|
|
|
72
105
|
});
|
|
73
106
|
}
|
|
74
107
|
|
|
75
|
-
function
|
|
76
|
-
return
|
|
108
|
+
function unsupportedFeatureMessage(thing) {
|
|
109
|
+
return `Unsupported feature: Translating "${thing}" is currently not supported.`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function buildCodeFrameForComment(node, message) {
|
|
113
|
+
return (0, _ErrorUtils.buildCodeFrame)(node, message, code, false);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function addErrorComment(node, message) {
|
|
117
|
+
var _node$comments;
|
|
118
|
+
|
|
119
|
+
const comment = {
|
|
120
|
+
type: 'Block',
|
|
121
|
+
value: `*${_os.EOL} * ${message.replace(new RegExp(_os.EOL, 'g'), `${_os.EOL} * `)}${_os.EOL}*`,
|
|
122
|
+
leading: true,
|
|
123
|
+
printed: false
|
|
124
|
+
};
|
|
125
|
+
code = makeCommentOwnLine(code, comment); // $FlowExpectedError[prop-missing]
|
|
126
|
+
// $FlowExpectedError[cannot-write]
|
|
127
|
+
|
|
128
|
+
(_node$comments = node.comments) != null ? _node$comments : node.comments = []; // $FlowExpectedError[prop-missing]
|
|
129
|
+
// $FlowExpectedError[incompatible-cast]
|
|
130
|
+
|
|
131
|
+
node.comments.push(comment);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function unsupportedAnnotation(node, thing) {
|
|
135
|
+
const message = unsupportedFeatureMessage(thing);
|
|
136
|
+
|
|
137
|
+
if (opts.recoverFromErrors) {
|
|
138
|
+
const codeFrame = buildCodeFrameForComment(node, message);
|
|
139
|
+
const newNode = {
|
|
140
|
+
type: 'TSAnyKeyword'
|
|
141
|
+
};
|
|
142
|
+
addErrorComment(newNode, codeFrame);
|
|
143
|
+
return newNode;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
throw translationError(node, message);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function unsupportedDeclaration(node, thing, id, declare = false, typeParameters = null) {
|
|
150
|
+
const message = unsupportedFeatureMessage(thing);
|
|
151
|
+
|
|
152
|
+
if (opts.recoverFromErrors) {
|
|
153
|
+
const codeFrame = buildCodeFrameForComment(node, message);
|
|
154
|
+
const newNode = {
|
|
155
|
+
type: 'TSTypeAliasDeclaration',
|
|
156
|
+
declare,
|
|
157
|
+
id: transform.Identifier(id, false),
|
|
158
|
+
typeAnnotation: {
|
|
159
|
+
type: 'TSAnyKeyword'
|
|
160
|
+
},
|
|
161
|
+
typeParameters: typeParameters == null ? undefined : transform.TypeParameterDeclaration(typeParameters)
|
|
162
|
+
};
|
|
163
|
+
addErrorComment(newNode, codeFrame);
|
|
164
|
+
return newNode;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
throw translationError(node, message);
|
|
77
168
|
}
|
|
78
169
|
|
|
79
170
|
const topScope = (() => {
|
|
@@ -87,7 +178,21 @@ const getTransforms = (code, scopeManager) => {
|
|
|
87
178
|
})();
|
|
88
179
|
|
|
89
180
|
function isReactImport(id) {
|
|
90
|
-
let currentScope =
|
|
181
|
+
let currentScope = (() => {
|
|
182
|
+
let scope = null;
|
|
183
|
+
let node = id;
|
|
184
|
+
|
|
185
|
+
while (!scope && node) {
|
|
186
|
+
scope = scopeManager.acquire(node, true);
|
|
187
|
+
node = node.parent;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return scope;
|
|
191
|
+
})();
|
|
192
|
+
|
|
193
|
+
if (currentScope == null) {
|
|
194
|
+
throw new Error('unable to resolve scope');
|
|
195
|
+
}
|
|
91
196
|
|
|
92
197
|
const variableDef = (() => {
|
|
93
198
|
while (currentScope != null) {
|
|
@@ -99,11 +204,12 @@ const getTransforms = (code, scopeManager) => {
|
|
|
99
204
|
|
|
100
205
|
currentScope = currentScope.upper;
|
|
101
206
|
}
|
|
102
|
-
})(); // No variable found, it
|
|
207
|
+
})(); // No variable found, it is not imported.
|
|
208
|
+
// It could be a global though if isValidReactImportOrGlobal returns true.
|
|
103
209
|
|
|
104
210
|
|
|
105
211
|
if (variableDef == null) {
|
|
106
|
-
return
|
|
212
|
+
return false;
|
|
107
213
|
}
|
|
108
214
|
|
|
109
215
|
const def = variableDef.defs[0]; // Detect:
|
|
@@ -133,6 +239,393 @@ const getTransforms = (code, scopeManager) => {
|
|
|
133
239
|
return false;
|
|
134
240
|
}
|
|
135
241
|
|
|
242
|
+
function EnumImpl(node) {
|
|
243
|
+
const body = node.body;
|
|
244
|
+
|
|
245
|
+
if (body.type === 'EnumSymbolBody') {
|
|
246
|
+
/*
|
|
247
|
+
There's unfortunately no way for us to support this in a clean way.
|
|
248
|
+
We can get really close using this code:
|
|
249
|
+
```
|
|
250
|
+
declare namespace SymbolEnum {
|
|
251
|
+
export const member1: unique symbol;
|
|
252
|
+
export type member1 = typeof member1;
|
|
253
|
+
export const member2: unique symbol;
|
|
254
|
+
export type member2 = typeof member2;
|
|
255
|
+
}
|
|
256
|
+
type SymbolEnum = typeof SymbolEnum[keyof typeof SymbolEnum];
|
|
257
|
+
```
|
|
258
|
+
However as explained in https://github.com/microsoft/TypeScript/issues/43657:
|
|
259
|
+
"A unique symbol type is never transferred from one declaration to another through inference."
|
|
260
|
+
This intended behaviour in TS means that the usage of the fake-enum would look like this:
|
|
261
|
+
```
|
|
262
|
+
const value: SymbolEnum.member1 = SymbolEnum.member1;
|
|
263
|
+
// ^^^^^^^^^^^^^^^^^^ required to force TS to retain the information
|
|
264
|
+
```
|
|
265
|
+
Which is really clunky and shitty. It definitely works, but ofc it's not good.
|
|
266
|
+
We can go with this design if users are okay with it!
|
|
267
|
+
Considering how rarely used symbol enums are ATM, let's just put a pin in it for now.
|
|
268
|
+
*/
|
|
269
|
+
return unsupportedDeclaration(node, 'symbol enums', node.id, FlowESTree.isDeclareEnum(node));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (body.type === 'EnumBooleanBody') {
|
|
273
|
+
/*
|
|
274
|
+
TODO - TS enums only allow strings or numbers as their values - not booleans.
|
|
275
|
+
This means we need a non-ts-enum representation of the enum.
|
|
276
|
+
We can support boolean enums using a construct like this:
|
|
277
|
+
```ts
|
|
278
|
+
declare namespace BooleanEnum {
|
|
279
|
+
export const member1: true;
|
|
280
|
+
export type member1 = typeof member1;
|
|
281
|
+
export const member2: false;
|
|
282
|
+
export type member2 = typeof member1;
|
|
283
|
+
}
|
|
284
|
+
declare type BooleanEnum = boolean;
|
|
285
|
+
```
|
|
286
|
+
But it's pretty clunky and ugly.
|
|
287
|
+
Considering how rarely used boolean enums are ATM, let's just put a pin in it for now.
|
|
288
|
+
*/
|
|
289
|
+
return unsupportedDeclaration(node, 'boolean enums', node.id, FlowESTree.isDeclareEnum(node));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const members = [];
|
|
293
|
+
|
|
294
|
+
for (const member of body.members) {
|
|
295
|
+
switch (member.type) {
|
|
296
|
+
case 'EnumDefaultedMember':
|
|
297
|
+
{
|
|
298
|
+
if (body.type === 'EnumNumberBody') {
|
|
299
|
+
// this should be impossible!
|
|
300
|
+
throw unexpectedTranslationError(member, 'Unexpected defaulted number enum member');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
members.push({
|
|
304
|
+
type: 'TSEnumMember',
|
|
305
|
+
computed: false,
|
|
306
|
+
id: transform.Identifier(member.id, false),
|
|
307
|
+
initializer: {
|
|
308
|
+
type: 'Literal',
|
|
309
|
+
raw: `"${member.id.name}"`,
|
|
310
|
+
value: member.id.name
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
case 'EnumNumberMember':
|
|
317
|
+
case 'EnumStringMember':
|
|
318
|
+
members.push({
|
|
319
|
+
type: 'TSEnumMember',
|
|
320
|
+
computed: false,
|
|
321
|
+
id: transform.Identifier(member.id, false),
|
|
322
|
+
initializer: member.init.literalType === 'string' ? transform.StringLiteral(member.init) : transform.NumericLiteral(member.init)
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const bodyRepresentationType = body.type === 'EnumNumberBody' ? {
|
|
328
|
+
type: 'TSNumberKeyword'
|
|
329
|
+
} : {
|
|
330
|
+
type: 'TSStringKeyword'
|
|
331
|
+
};
|
|
332
|
+
const enumName = transform.Identifier(node.id, false);
|
|
333
|
+
return [{
|
|
334
|
+
type: 'TSEnumDeclaration',
|
|
335
|
+
const: false,
|
|
336
|
+
declare: true,
|
|
337
|
+
id: enumName,
|
|
338
|
+
members
|
|
339
|
+
}, // flow also exports `.cast`, `.isValid`, `.members` and `.getName` for enums
|
|
340
|
+
// we can use declaration merging to declare these functions on the enum:
|
|
341
|
+
|
|
342
|
+
/*
|
|
343
|
+
declare enum Foo {
|
|
344
|
+
A = 1,
|
|
345
|
+
B = 2,
|
|
346
|
+
}
|
|
347
|
+
declare namespace Foo {
|
|
348
|
+
export function cast(value: number | null | undefined): Foo;
|
|
349
|
+
export function isValid(value: number | null | undefined): value is Foo;
|
|
350
|
+
export function members(): IterableIterator<Foo>;
|
|
351
|
+
export function getName(value: Foo): string;
|
|
352
|
+
}
|
|
353
|
+
*/
|
|
354
|
+
{
|
|
355
|
+
type: 'TSModuleDeclaration',
|
|
356
|
+
declare: true,
|
|
357
|
+
id: enumName,
|
|
358
|
+
body: {
|
|
359
|
+
type: 'TSModuleBlock',
|
|
360
|
+
body: [// export function cast(value: number | null | undefined): Foo
|
|
361
|
+
{
|
|
362
|
+
type: 'ExportNamedDeclaration',
|
|
363
|
+
declaration: {
|
|
364
|
+
type: 'TSDeclareFunction',
|
|
365
|
+
id: {
|
|
366
|
+
type: 'Identifier',
|
|
367
|
+
name: 'cast'
|
|
368
|
+
},
|
|
369
|
+
generator: false,
|
|
370
|
+
expression: false,
|
|
371
|
+
async: false,
|
|
372
|
+
params: [{
|
|
373
|
+
type: 'Identifier',
|
|
374
|
+
name: 'value',
|
|
375
|
+
typeAnnotation: {
|
|
376
|
+
type: 'TSTypeAnnotation',
|
|
377
|
+
typeAnnotation: {
|
|
378
|
+
type: 'TSUnionType',
|
|
379
|
+
types: [bodyRepresentationType, {
|
|
380
|
+
type: 'TSNullKeyword'
|
|
381
|
+
}, {
|
|
382
|
+
type: 'TSUndefinedKeyword'
|
|
383
|
+
}]
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}],
|
|
387
|
+
returnType: {
|
|
388
|
+
type: 'TSTypeAnnotation',
|
|
389
|
+
typeAnnotation: {
|
|
390
|
+
type: 'TSTypeReference',
|
|
391
|
+
typeName: enumName
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
specifiers: [],
|
|
396
|
+
source: null,
|
|
397
|
+
exportKind: 'value',
|
|
398
|
+
assertions: []
|
|
399
|
+
}, // export function isValid(value: number | null | undefined): value is Foo;
|
|
400
|
+
{
|
|
401
|
+
type: 'ExportNamedDeclaration',
|
|
402
|
+
declaration: {
|
|
403
|
+
type: 'TSDeclareFunction',
|
|
404
|
+
id: {
|
|
405
|
+
type: 'Identifier',
|
|
406
|
+
name: 'isValid'
|
|
407
|
+
},
|
|
408
|
+
generator: false,
|
|
409
|
+
expression: false,
|
|
410
|
+
async: false,
|
|
411
|
+
params: [{
|
|
412
|
+
type: 'Identifier',
|
|
413
|
+
name: 'value',
|
|
414
|
+
typeAnnotation: {
|
|
415
|
+
type: 'TSTypeAnnotation',
|
|
416
|
+
typeAnnotation: {
|
|
417
|
+
type: 'TSUnionType',
|
|
418
|
+
types: [bodyRepresentationType, {
|
|
419
|
+
type: 'TSNullKeyword'
|
|
420
|
+
}, {
|
|
421
|
+
type: 'TSUndefinedKeyword'
|
|
422
|
+
}]
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}],
|
|
426
|
+
returnType: {
|
|
427
|
+
type: 'TSTypeAnnotation',
|
|
428
|
+
typeAnnotation: {
|
|
429
|
+
type: 'TSTypePredicate',
|
|
430
|
+
asserts: false,
|
|
431
|
+
parameterName: {
|
|
432
|
+
type: 'Identifier',
|
|
433
|
+
name: 'value'
|
|
434
|
+
},
|
|
435
|
+
typeAnnotation: {
|
|
436
|
+
type: 'TSTypeAnnotation',
|
|
437
|
+
typeAnnotation: {
|
|
438
|
+
type: 'TSTypeReference',
|
|
439
|
+
typeName: enumName
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
specifiers: [],
|
|
446
|
+
source: null,
|
|
447
|
+
exportKind: 'value',
|
|
448
|
+
assertions: []
|
|
449
|
+
}, // export function members(): IterableIterator<Foo>;
|
|
450
|
+
{
|
|
451
|
+
type: 'ExportNamedDeclaration',
|
|
452
|
+
declaration: {
|
|
453
|
+
type: 'TSDeclareFunction',
|
|
454
|
+
id: {
|
|
455
|
+
type: 'Identifier',
|
|
456
|
+
name: 'members'
|
|
457
|
+
},
|
|
458
|
+
generator: false,
|
|
459
|
+
expression: false,
|
|
460
|
+
async: false,
|
|
461
|
+
params: [],
|
|
462
|
+
returnType: {
|
|
463
|
+
type: 'TSTypeAnnotation',
|
|
464
|
+
typeAnnotation: {
|
|
465
|
+
type: 'TSTypeReference',
|
|
466
|
+
typeName: {
|
|
467
|
+
type: 'Identifier',
|
|
468
|
+
name: 'IterableIterator'
|
|
469
|
+
},
|
|
470
|
+
typeParameters: {
|
|
471
|
+
type: 'TSTypeParameterInstantiation',
|
|
472
|
+
params: [{
|
|
473
|
+
type: 'TSTypeReference',
|
|
474
|
+
typeName: enumName
|
|
475
|
+
}]
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
specifiers: [],
|
|
481
|
+
source: null,
|
|
482
|
+
exportKind: 'value',
|
|
483
|
+
assertions: []
|
|
484
|
+
}, // export function getName(value: Foo): string;
|
|
485
|
+
{
|
|
486
|
+
type: 'ExportNamedDeclaration',
|
|
487
|
+
declaration: {
|
|
488
|
+
type: 'TSDeclareFunction',
|
|
489
|
+
id: {
|
|
490
|
+
type: 'Identifier',
|
|
491
|
+
name: 'getName'
|
|
492
|
+
},
|
|
493
|
+
generator: false,
|
|
494
|
+
expression: false,
|
|
495
|
+
async: false,
|
|
496
|
+
params: [{
|
|
497
|
+
type: 'Identifier',
|
|
498
|
+
name: 'value',
|
|
499
|
+
typeAnnotation: {
|
|
500
|
+
type: 'TSTypeAnnotation',
|
|
501
|
+
typeAnnotation: {
|
|
502
|
+
type: 'TSTypeReference',
|
|
503
|
+
typeName: enumName
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}],
|
|
507
|
+
returnType: {
|
|
508
|
+
type: 'TSTypeAnnotation',
|
|
509
|
+
typeAnnotation: {
|
|
510
|
+
type: 'TSStringKeyword'
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
specifiers: [],
|
|
515
|
+
source: null,
|
|
516
|
+
exportKind: 'value',
|
|
517
|
+
assertions: []
|
|
518
|
+
}]
|
|
519
|
+
}
|
|
520
|
+
}];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
const getPlaceholderNameForTypeofImport = (() => {
|
|
524
|
+
let typeof_import_count = 0;
|
|
525
|
+
return () => `$$IMPORT_TYPEOF_${++typeof_import_count}$$`;
|
|
526
|
+
})();
|
|
527
|
+
|
|
528
|
+
const transformTypeAnnotationType = node => {
|
|
529
|
+
switch (node.type) {
|
|
530
|
+
case 'AnyTypeAnnotation':
|
|
531
|
+
return transform.AnyTypeAnnotation(node);
|
|
532
|
+
|
|
533
|
+
case 'ArrayTypeAnnotation':
|
|
534
|
+
return transform.ArrayTypeAnnotation(node);
|
|
535
|
+
|
|
536
|
+
case 'BigIntLiteralTypeAnnotation':
|
|
537
|
+
return transform.BigIntLiteralTypeAnnotation(node);
|
|
538
|
+
|
|
539
|
+
case 'BigIntTypeAnnotation':
|
|
540
|
+
return transform.BigIntTypeAnnotation(node);
|
|
541
|
+
|
|
542
|
+
case 'BooleanLiteralTypeAnnotation':
|
|
543
|
+
return transform.BooleanLiteralTypeAnnotation(node);
|
|
544
|
+
|
|
545
|
+
case 'BooleanTypeAnnotation':
|
|
546
|
+
return transform.BooleanTypeAnnotation(node);
|
|
547
|
+
|
|
548
|
+
case 'EmptyTypeAnnotation':
|
|
549
|
+
return transform.EmptyTypeAnnotation(node);
|
|
550
|
+
|
|
551
|
+
case 'ExistsTypeAnnotation':
|
|
552
|
+
return transform.ExistsTypeAnnotation(node);
|
|
553
|
+
|
|
554
|
+
case 'FunctionTypeAnnotation':
|
|
555
|
+
return transform.FunctionTypeAnnotation(node);
|
|
556
|
+
|
|
557
|
+
case 'GenericTypeAnnotation':
|
|
558
|
+
return transform.GenericTypeAnnotation(node);
|
|
559
|
+
|
|
560
|
+
case 'IndexedAccessType':
|
|
561
|
+
return transform.IndexedAccessType(node);
|
|
562
|
+
|
|
563
|
+
case 'InterfaceTypeAnnotation':
|
|
564
|
+
return transform.InterfaceTypeAnnotation(node);
|
|
565
|
+
|
|
566
|
+
case 'IntersectionTypeAnnotation':
|
|
567
|
+
return transform.IntersectionTypeAnnotation(node);
|
|
568
|
+
|
|
569
|
+
case 'MixedTypeAnnotation':
|
|
570
|
+
return transform.MixedTypeAnnotation(node);
|
|
571
|
+
|
|
572
|
+
case 'NullLiteralTypeAnnotation':
|
|
573
|
+
return transform.NullLiteralTypeAnnotation(node);
|
|
574
|
+
|
|
575
|
+
case 'NullableTypeAnnotation':
|
|
576
|
+
return transform.NullableTypeAnnotation(node);
|
|
577
|
+
|
|
578
|
+
case 'NumberLiteralTypeAnnotation':
|
|
579
|
+
return transform.NumberLiteralTypeAnnotation(node);
|
|
580
|
+
|
|
581
|
+
case 'NumberTypeAnnotation':
|
|
582
|
+
return transform.NumberTypeAnnotation(node);
|
|
583
|
+
|
|
584
|
+
case 'ObjectTypeAnnotation':
|
|
585
|
+
return transform.ObjectTypeAnnotation(node);
|
|
586
|
+
|
|
587
|
+
case 'OptionalIndexedAccessType':
|
|
588
|
+
return transform.OptionalIndexedAccessType(node);
|
|
589
|
+
|
|
590
|
+
case 'QualifiedTypeIdentifier':
|
|
591
|
+
return transform.QualifiedTypeIdentifier(node);
|
|
592
|
+
|
|
593
|
+
case 'StringLiteralTypeAnnotation':
|
|
594
|
+
return transform.StringLiteralTypeAnnotation(node);
|
|
595
|
+
|
|
596
|
+
case 'StringTypeAnnotation':
|
|
597
|
+
return transform.StringTypeAnnotation(node);
|
|
598
|
+
|
|
599
|
+
case 'SymbolTypeAnnotation':
|
|
600
|
+
return transform.SymbolTypeAnnotation(node);
|
|
601
|
+
|
|
602
|
+
case 'ThisTypeAnnotation':
|
|
603
|
+
return transform.ThisTypeAnnotation(node);
|
|
604
|
+
|
|
605
|
+
case 'TupleTypeAnnotation':
|
|
606
|
+
return transform.TupleTypeAnnotation(node);
|
|
607
|
+
|
|
608
|
+
case 'TupleTypeLabeledElement':
|
|
609
|
+
case 'TupleTypeSpreadElement':
|
|
610
|
+
return unsupportedAnnotation(node, node.type);
|
|
611
|
+
|
|
612
|
+
case 'TypeofTypeAnnotation':
|
|
613
|
+
return transform.TypeofTypeAnnotation(node);
|
|
614
|
+
|
|
615
|
+
case 'UnionTypeAnnotation':
|
|
616
|
+
return transform.UnionTypeAnnotation(node);
|
|
617
|
+
|
|
618
|
+
case 'VoidTypeAnnotation':
|
|
619
|
+
return transform.VoidTypeAnnotation(node);
|
|
620
|
+
|
|
621
|
+
case 'TypePredicate':
|
|
622
|
+
return unsupportedAnnotation(node, node.type);
|
|
623
|
+
|
|
624
|
+
default:
|
|
625
|
+
throw unexpectedTranslationError(node, `Unhandled type ${node.type}`);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
136
629
|
const transform = {
|
|
137
630
|
AnyTypeAnnotation(_node) {
|
|
138
631
|
return {
|
|
@@ -143,7 +636,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
143
636
|
ArrayTypeAnnotation(node) {
|
|
144
637
|
return {
|
|
145
638
|
type: 'TSArrayType',
|
|
146
|
-
elementType:
|
|
639
|
+
elementType: transformTypeAnnotationType(node.elementType)
|
|
147
640
|
};
|
|
148
641
|
},
|
|
149
642
|
|
|
@@ -221,7 +714,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
221
714
|
const transformedBody = transform.ObjectTypeAnnotation(node.body);
|
|
222
715
|
|
|
223
716
|
if (transformedBody.type !== 'TSTypeLiteral') {
|
|
224
|
-
|
|
717
|
+
return unsupportedDeclaration(node.body, 'Spreads in declare class are not allowed', node.id, true, node.typeParameters);
|
|
225
718
|
}
|
|
226
719
|
|
|
227
720
|
for (const member of transformedBody.members) {
|
|
@@ -348,7 +841,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
348
841
|
```
|
|
349
842
|
Let's put a pin in it for now and deal with it later if the need arises.
|
|
350
843
|
*/
|
|
351
|
-
|
|
844
|
+
return unsupportedDeclaration((_node$body$callProper = node.body.callProperties[0]) != null ? _node$body$callProper : node.body, 'call signatures on classes', node.id, true, node.typeParameters);
|
|
352
845
|
}
|
|
353
846
|
|
|
354
847
|
default:
|
|
@@ -492,7 +985,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
492
985
|
name: SPECIFIER,
|
|
493
986
|
typeAnnotation: {
|
|
494
987
|
type: 'TSTypeAnnotation',
|
|
495
|
-
typeAnnotation:
|
|
988
|
+
typeAnnotation: transformTypeAnnotationType(declaration)
|
|
496
989
|
}
|
|
497
990
|
},
|
|
498
991
|
init: null
|
|
@@ -526,44 +1019,59 @@ const getTransforms = (code, scopeManager) => {
|
|
|
526
1019
|
};
|
|
527
1020
|
}
|
|
528
1021
|
|
|
529
|
-
const {
|
|
530
|
-
declaration,
|
|
531
|
-
exportKind
|
|
532
|
-
} = (() => {
|
|
1022
|
+
const declarations = (() => {
|
|
533
1023
|
switch (node.declaration.type) {
|
|
534
1024
|
case 'DeclareClass':
|
|
535
|
-
return {
|
|
1025
|
+
return [{
|
|
536
1026
|
declaration: transform.DeclareClass(node.declaration),
|
|
537
1027
|
exportKind: 'value'
|
|
538
|
-
};
|
|
1028
|
+
}];
|
|
539
1029
|
|
|
540
1030
|
case 'DeclareFunction':
|
|
541
|
-
return {
|
|
1031
|
+
return [{
|
|
542
1032
|
declaration: transform.DeclareFunction(node.declaration),
|
|
543
1033
|
exportKind: 'value'
|
|
544
|
-
};
|
|
1034
|
+
}];
|
|
545
1035
|
|
|
546
1036
|
case 'DeclareInterface':
|
|
547
|
-
return {
|
|
1037
|
+
return [{
|
|
548
1038
|
declaration: transform.DeclareInterface(node.declaration),
|
|
549
1039
|
exportKind: 'type'
|
|
550
|
-
};
|
|
1040
|
+
}];
|
|
551
1041
|
|
|
552
1042
|
case 'DeclareOpaqueType':
|
|
553
|
-
return {
|
|
1043
|
+
return [{
|
|
554
1044
|
declaration: transform.DeclareOpaqueType(node.declaration),
|
|
555
1045
|
exportKind: 'type'
|
|
556
|
-
};
|
|
1046
|
+
}];
|
|
557
1047
|
|
|
558
1048
|
case 'DeclareVariable':
|
|
559
|
-
return {
|
|
1049
|
+
return [{
|
|
560
1050
|
declaration: transform.DeclareVariable(node.declaration),
|
|
561
1051
|
exportKind: 'value'
|
|
562
|
-
};
|
|
1052
|
+
}];
|
|
1053
|
+
|
|
1054
|
+
case 'DeclareEnum':
|
|
1055
|
+
{
|
|
1056
|
+
const result = transform.DeclareEnum(node.declaration);
|
|
1057
|
+
return Array.isArray(result) ? [{
|
|
1058
|
+
declaration: result[0],
|
|
1059
|
+
exportKind: 'type'
|
|
1060
|
+
}, {
|
|
1061
|
+
declaration: result[1],
|
|
1062
|
+
exportKind: 'type'
|
|
1063
|
+
}] : [{
|
|
1064
|
+
declaration: result,
|
|
1065
|
+
exportKind: 'type'
|
|
1066
|
+
}];
|
|
1067
|
+
}
|
|
563
1068
|
}
|
|
564
1069
|
})();
|
|
565
1070
|
|
|
566
|
-
return {
|
|
1071
|
+
return declarations.map(({
|
|
1072
|
+
declaration,
|
|
1073
|
+
exportKind
|
|
1074
|
+
}) => ({
|
|
567
1075
|
type: 'ExportNamedDeclaration',
|
|
568
1076
|
// flow does not currently support assertions
|
|
569
1077
|
assertions: [],
|
|
@@ -571,7 +1079,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
571
1079
|
exportKind,
|
|
572
1080
|
source: null,
|
|
573
1081
|
specifiers: []
|
|
574
|
-
};
|
|
1082
|
+
}));
|
|
575
1083
|
} else {
|
|
576
1084
|
return {
|
|
577
1085
|
type: 'ExportNamedDeclaration',
|
|
@@ -633,7 +1141,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
633
1141
|
type: 'TSTypeAliasDeclaration',
|
|
634
1142
|
declare: node.type === 'DeclareTypeAlias',
|
|
635
1143
|
id: transform.Identifier(node.id, false),
|
|
636
|
-
typeAnnotation:
|
|
1144
|
+
typeAnnotation: transformTypeAnnotationType(node.right),
|
|
637
1145
|
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
638
1146
|
};
|
|
639
1147
|
},
|
|
@@ -647,313 +1155,40 @@ const getTransforms = (code, scopeManager) => {
|
|
|
647
1155
|
declare: true,
|
|
648
1156
|
id: transform.Identifier(node.id, false),
|
|
649
1157
|
typeAnnotation: node.supertype == null ? {
|
|
650
|
-
type: 'TSUnknownKeyword'
|
|
651
|
-
} :
|
|
652
|
-
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
653
|
-
};
|
|
654
|
-
},
|
|
655
|
-
|
|
656
|
-
DeclareVariable(node) {
|
|
657
|
-
return {
|
|
658
|
-
type: 'VariableDeclaration',
|
|
659
|
-
declare: true,
|
|
660
|
-
declarations: [{
|
|
661
|
-
type: 'VariableDeclarator',
|
|
662
|
-
declare: true,
|
|
663
|
-
id: transform.Identifier(node.id, true),
|
|
664
|
-
init: null
|
|
665
|
-
}],
|
|
666
|
-
kind:
|
|
667
|
-
};
|
|
668
|
-
},
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
We can get really close using this code:
|
|
685
|
-
```
|
|
686
|
-
declare namespace SymbolEnum {
|
|
687
|
-
export const member1: unique symbol;
|
|
688
|
-
export type member1 = typeof member1;
|
|
689
|
-
export const member2: unique symbol;
|
|
690
|
-
export type member2 = typeof member2;
|
|
691
|
-
}
|
|
692
|
-
type SymbolEnum = typeof SymbolEnum[keyof typeof SymbolEnum];
|
|
693
|
-
```
|
|
694
|
-
However as explained in https://github.com/microsoft/TypeScript/issues/43657:
|
|
695
|
-
"A unique symbol type is never transferred from one declaration to another through inference."
|
|
696
|
-
This intended behaviour in TS means that the usage of the fake-enum would look like this:
|
|
697
|
-
```
|
|
698
|
-
const value: SymbolEnum.member1 = SymbolEnum.member1;
|
|
699
|
-
// ^^^^^^^^^^^^^^^^^^ required to force TS to retain the information
|
|
700
|
-
```
|
|
701
|
-
Which is really clunky and shitty. It definitely works, but ofc it's not good.
|
|
702
|
-
We can go with this design if users are okay with it!
|
|
703
|
-
Considering how rarely used symbol enums are ATM, let's just put a pin in it for now.
|
|
704
|
-
*/
|
|
705
|
-
throw unsupportedTranslationError(node, 'symbol enums');
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
if (body.type === 'EnumBooleanBody') {
|
|
709
|
-
/*
|
|
710
|
-
TODO - TS enums only allow strings or numbers as their values - not booleans.
|
|
711
|
-
This means we need a non-ts-enum representation of the enum.
|
|
712
|
-
We can support boolean enums using a construct like this:
|
|
713
|
-
```ts
|
|
714
|
-
declare namespace BooleanEnum {
|
|
715
|
-
export const member1: true;
|
|
716
|
-
export type member1 = typeof member1;
|
|
717
|
-
export const member2: false;
|
|
718
|
-
export type member2 = typeof member1;
|
|
719
|
-
}
|
|
720
|
-
declare type BooleanEnum = boolean;
|
|
721
|
-
```
|
|
722
|
-
But it's pretty clunky and ugly.
|
|
723
|
-
Considering how rarely used boolean enums are ATM, let's just put a pin in it for now.
|
|
724
|
-
*/
|
|
725
|
-
throw unsupportedTranslationError(node, 'boolean enums');
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
const members = [];
|
|
729
|
-
|
|
730
|
-
for (const member of body.members) {
|
|
731
|
-
switch (member.type) {
|
|
732
|
-
case 'EnumDefaultedMember':
|
|
733
|
-
{
|
|
734
|
-
if (body.type === 'EnumNumberBody') {
|
|
735
|
-
// this should be impossible!
|
|
736
|
-
throw unexpectedTranslationError(member, 'Unexpected defaulted number enum member');
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
members.push({
|
|
740
|
-
type: 'TSEnumMember',
|
|
741
|
-
computed: false,
|
|
742
|
-
id: transform.Identifier(member.id, false),
|
|
743
|
-
initializer: {
|
|
744
|
-
type: 'Literal',
|
|
745
|
-
raw: `"${member.id.name}"`,
|
|
746
|
-
value: member.id.name
|
|
747
|
-
}
|
|
748
|
-
});
|
|
749
|
-
break;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
case 'EnumNumberMember':
|
|
753
|
-
case 'EnumStringMember':
|
|
754
|
-
members.push({
|
|
755
|
-
type: 'TSEnumMember',
|
|
756
|
-
computed: false,
|
|
757
|
-
id: transform.Identifier(member.id, false),
|
|
758
|
-
initializer: member.init.literalType === 'string' ? transform.StringLiteral(member.init) : transform.NumericLiteral(member.init)
|
|
759
|
-
});
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
const bodyRepresentationType = body.type === 'EnumNumberBody' ? {
|
|
764
|
-
type: 'TSNumberKeyword'
|
|
765
|
-
} : {
|
|
766
|
-
type: 'TSStringKeyword'
|
|
767
|
-
};
|
|
768
|
-
const enumName = transform.Identifier(node.id, false);
|
|
769
|
-
return [{
|
|
770
|
-
type: 'TSEnumDeclaration',
|
|
771
|
-
const: false,
|
|
772
|
-
declare: true,
|
|
773
|
-
id: enumName,
|
|
774
|
-
members
|
|
775
|
-
}, // flow also exports `.cast`, `.isValid`, `.members` and `.getName` for enums
|
|
776
|
-
// we can use declaration merging to declare these functions on the enum:
|
|
777
|
-
|
|
778
|
-
/*
|
|
779
|
-
declare enum Foo {
|
|
780
|
-
A = 1,
|
|
781
|
-
B = 2,
|
|
782
|
-
}
|
|
783
|
-
declare namespace Foo {
|
|
784
|
-
export function cast(value: number | null | undefined): Foo;
|
|
785
|
-
export function isValid(value: number | null | undefined): value is Foo;
|
|
786
|
-
export function members(): IterableIterator<Foo>;
|
|
787
|
-
export function getName(value: Foo): string;
|
|
788
|
-
}
|
|
789
|
-
*/
|
|
790
|
-
{
|
|
791
|
-
type: 'TSModuleDeclaration',
|
|
792
|
-
declare: true,
|
|
793
|
-
id: enumName,
|
|
794
|
-
body: {
|
|
795
|
-
type: 'TSModuleBlock',
|
|
796
|
-
body: [// export function cast(value: number | null | undefined): Foo
|
|
797
|
-
{
|
|
798
|
-
type: 'ExportNamedDeclaration',
|
|
799
|
-
declaration: {
|
|
800
|
-
type: 'TSDeclareFunction',
|
|
801
|
-
id: {
|
|
802
|
-
type: 'Identifier',
|
|
803
|
-
name: 'cast'
|
|
804
|
-
},
|
|
805
|
-
generator: false,
|
|
806
|
-
expression: false,
|
|
807
|
-
async: false,
|
|
808
|
-
params: [{
|
|
809
|
-
type: 'Identifier',
|
|
810
|
-
name: 'value',
|
|
811
|
-
typeAnnotation: {
|
|
812
|
-
type: 'TSTypeAnnotation',
|
|
813
|
-
typeAnnotation: {
|
|
814
|
-
type: 'TSUnionType',
|
|
815
|
-
types: [bodyRepresentationType, {
|
|
816
|
-
type: 'TSNullKeyword'
|
|
817
|
-
}, {
|
|
818
|
-
type: 'TSUndefinedKeyword'
|
|
819
|
-
}]
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
}],
|
|
823
|
-
returnType: {
|
|
824
|
-
type: 'TSTypeAnnotation',
|
|
825
|
-
typeAnnotation: {
|
|
826
|
-
type: 'TSTypeReference',
|
|
827
|
-
typeName: enumName
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
},
|
|
831
|
-
specifiers: [],
|
|
832
|
-
source: null,
|
|
833
|
-
exportKind: 'value',
|
|
834
|
-
assertions: []
|
|
835
|
-
}, // export function isValid(value: number | null | undefined): value is Foo;
|
|
836
|
-
{
|
|
837
|
-
type: 'ExportNamedDeclaration',
|
|
838
|
-
declaration: {
|
|
839
|
-
type: 'TSDeclareFunction',
|
|
840
|
-
id: {
|
|
841
|
-
type: 'Identifier',
|
|
842
|
-
name: 'isValid'
|
|
843
|
-
},
|
|
844
|
-
generator: false,
|
|
845
|
-
expression: false,
|
|
846
|
-
async: false,
|
|
847
|
-
params: [{
|
|
848
|
-
type: 'Identifier',
|
|
849
|
-
name: 'value',
|
|
850
|
-
typeAnnotation: {
|
|
851
|
-
type: 'TSTypeAnnotation',
|
|
852
|
-
typeAnnotation: {
|
|
853
|
-
type: 'TSUnionType',
|
|
854
|
-
types: [bodyRepresentationType, {
|
|
855
|
-
type: 'TSNullKeyword'
|
|
856
|
-
}, {
|
|
857
|
-
type: 'TSUndefinedKeyword'
|
|
858
|
-
}]
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}],
|
|
862
|
-
returnType: {
|
|
863
|
-
type: 'TSTypeAnnotation',
|
|
864
|
-
typeAnnotation: {
|
|
865
|
-
type: 'TSTypePredicate',
|
|
866
|
-
asserts: false,
|
|
867
|
-
parameterName: {
|
|
868
|
-
type: 'Identifier',
|
|
869
|
-
name: 'value'
|
|
870
|
-
},
|
|
871
|
-
typeAnnotation: {
|
|
872
|
-
type: 'TSTypeAnnotation',
|
|
873
|
-
typeAnnotation: {
|
|
874
|
-
type: 'TSTypeReference',
|
|
875
|
-
typeName: enumName
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
},
|
|
881
|
-
specifiers: [],
|
|
882
|
-
source: null,
|
|
883
|
-
exportKind: 'value',
|
|
884
|
-
assertions: []
|
|
885
|
-
}, // export function members(): IterableIterator<Foo>;
|
|
886
|
-
{
|
|
887
|
-
type: 'ExportNamedDeclaration',
|
|
888
|
-
declaration: {
|
|
889
|
-
type: 'TSDeclareFunction',
|
|
890
|
-
id: {
|
|
891
|
-
type: 'Identifier',
|
|
892
|
-
name: 'members'
|
|
893
|
-
},
|
|
894
|
-
generator: false,
|
|
895
|
-
expression: false,
|
|
896
|
-
async: false,
|
|
897
|
-
params: [],
|
|
898
|
-
returnType: {
|
|
899
|
-
type: 'TSTypeAnnotation',
|
|
900
|
-
typeAnnotation: {
|
|
901
|
-
type: 'TSTypeReference',
|
|
902
|
-
typeName: {
|
|
903
|
-
type: 'Identifier',
|
|
904
|
-
name: 'IterableIterator'
|
|
905
|
-
},
|
|
906
|
-
typeParameters: {
|
|
907
|
-
type: 'TSTypeParameterInstantiation',
|
|
908
|
-
params: [{
|
|
909
|
-
type: 'TSTypeReference',
|
|
910
|
-
typeName: enumName
|
|
911
|
-
}]
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
},
|
|
916
|
-
specifiers: [],
|
|
917
|
-
source: null,
|
|
918
|
-
exportKind: 'value',
|
|
919
|
-
assertions: []
|
|
920
|
-
}, // export function getName(value: Foo): string;
|
|
921
|
-
{
|
|
922
|
-
type: 'ExportNamedDeclaration',
|
|
923
|
-
declaration: {
|
|
924
|
-
type: 'TSDeclareFunction',
|
|
925
|
-
id: {
|
|
926
|
-
type: 'Identifier',
|
|
927
|
-
name: 'getName'
|
|
928
|
-
},
|
|
929
|
-
generator: false,
|
|
930
|
-
expression: false,
|
|
931
|
-
async: false,
|
|
932
|
-
params: [{
|
|
933
|
-
type: 'Identifier',
|
|
934
|
-
name: 'value',
|
|
935
|
-
typeAnnotation: {
|
|
936
|
-
type: 'TSTypeAnnotation',
|
|
937
|
-
typeAnnotation: {
|
|
938
|
-
type: 'TSTypeReference',
|
|
939
|
-
typeName: enumName
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}],
|
|
943
|
-
returnType: {
|
|
944
|
-
type: 'TSTypeAnnotation',
|
|
945
|
-
typeAnnotation: {
|
|
946
|
-
type: 'TSStringKeyword'
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
},
|
|
950
|
-
specifiers: [],
|
|
951
|
-
source: null,
|
|
952
|
-
exportKind: 'value',
|
|
953
|
-
assertions: []
|
|
954
|
-
}]
|
|
955
|
-
}
|
|
956
|
-
}];
|
|
1158
|
+
type: 'TSUnknownKeyword'
|
|
1159
|
+
} : transformTypeAnnotationType(node.supertype),
|
|
1160
|
+
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
1161
|
+
};
|
|
1162
|
+
},
|
|
1163
|
+
|
|
1164
|
+
DeclareVariable(node) {
|
|
1165
|
+
return {
|
|
1166
|
+
type: 'VariableDeclaration',
|
|
1167
|
+
declare: true,
|
|
1168
|
+
declarations: [{
|
|
1169
|
+
type: 'VariableDeclarator',
|
|
1170
|
+
declare: true,
|
|
1171
|
+
id: transform.Identifier(node.id, true),
|
|
1172
|
+
init: null
|
|
1173
|
+
}],
|
|
1174
|
+
kind: node.kind
|
|
1175
|
+
};
|
|
1176
|
+
},
|
|
1177
|
+
|
|
1178
|
+
DeclareEnum(node) {
|
|
1179
|
+
return EnumImpl(node);
|
|
1180
|
+
},
|
|
1181
|
+
|
|
1182
|
+
EmptyTypeAnnotation(node) {
|
|
1183
|
+
// Flow's `empty` type doesn't map well to any types in TS.
|
|
1184
|
+
// The closest is `never`, but `never` has a number of different semantics
|
|
1185
|
+
// In reality no human code should ever directly use the `empty` type in flow
|
|
1186
|
+
// So let's put a pin in it for now
|
|
1187
|
+
return unsupportedAnnotation(node, 'empty type');
|
|
1188
|
+
},
|
|
1189
|
+
|
|
1190
|
+
EnumDeclaration(node) {
|
|
1191
|
+
return EnumImpl(node);
|
|
957
1192
|
},
|
|
958
1193
|
|
|
959
1194
|
DeclareModuleExports(node) {
|
|
@@ -963,7 +1198,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
963
1198
|
ExistsTypeAnnotation(node) {
|
|
964
1199
|
// The existential type does not map to any types in TS
|
|
965
1200
|
// It's also super deprecated - so let's not ever worry
|
|
966
|
-
|
|
1201
|
+
return unsupportedAnnotation(node, 'existential type');
|
|
967
1202
|
},
|
|
968
1203
|
|
|
969
1204
|
ExportNamedDeclaration(node) {
|
|
@@ -982,11 +1217,12 @@ const getTransforms = (code, scopeManager) => {
|
|
|
982
1217
|
|
|
983
1218
|
const [exportedDeclaration, mergedDeclaration] = (() => {
|
|
984
1219
|
if (node.declaration == null) {
|
|
985
|
-
return [null];
|
|
1220
|
+
return [null, null];
|
|
986
1221
|
}
|
|
987
1222
|
|
|
988
1223
|
switch (node.declaration.type) {
|
|
989
1224
|
case 'ClassDeclaration':
|
|
1225
|
+
case 'ComponentDeclaration':
|
|
990
1226
|
case 'FunctionDeclaration':
|
|
991
1227
|
case 'VariableDeclaration':
|
|
992
1228
|
// These cases shouldn't happen in flow defs because they have their own special
|
|
@@ -994,7 +1230,10 @@ const getTransforms = (code, scopeManager) => {
|
|
|
994
1230
|
throw unexpectedTranslationError(node.declaration, `Unexpected named declaration found ${node.declaration.type}`);
|
|
995
1231
|
|
|
996
1232
|
case 'EnumDeclaration':
|
|
997
|
-
|
|
1233
|
+
{
|
|
1234
|
+
const result = transform.EnumDeclaration(node.declaration);
|
|
1235
|
+
return Array.isArray(result) ? result : [result, null];
|
|
1236
|
+
}
|
|
998
1237
|
|
|
999
1238
|
case 'InterfaceDeclaration':
|
|
1000
1239
|
return [transform.InterfaceDeclaration(node.declaration), null];
|
|
@@ -1050,7 +1289,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1050
1289
|
name: 'this',
|
|
1051
1290
|
typeAnnotation: {
|
|
1052
1291
|
type: 'TSTypeAnnotation',
|
|
1053
|
-
typeAnnotation:
|
|
1292
|
+
typeAnnotation: transformTypeAnnotationType(node.this.typeAnnotation)
|
|
1054
1293
|
}
|
|
1055
1294
|
});
|
|
1056
1295
|
}
|
|
@@ -1065,7 +1304,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1065
1304
|
} : transform.Identifier(rest.name, false),
|
|
1066
1305
|
typeAnnotation: {
|
|
1067
1306
|
type: 'TSTypeAnnotation',
|
|
1068
|
-
typeAnnotation:
|
|
1307
|
+
typeAnnotation: transformTypeAnnotationType(rest.typeAnnotation)
|
|
1069
1308
|
}
|
|
1070
1309
|
});
|
|
1071
1310
|
}
|
|
@@ -1075,7 +1314,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1075
1314
|
params,
|
|
1076
1315
|
returnType: {
|
|
1077
1316
|
type: 'TSTypeAnnotation',
|
|
1078
|
-
typeAnnotation:
|
|
1317
|
+
typeAnnotation: transformTypeAnnotationType(node.returnType)
|
|
1079
1318
|
},
|
|
1080
1319
|
typeParameters: node.typeParameters == null ? undefined : transform.TypeParameterDeclaration(node.typeParameters)
|
|
1081
1320
|
};
|
|
@@ -1087,7 +1326,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1087
1326
|
name: node.name == null ? `$$PARAM_${idx}$$` : node.name.name,
|
|
1088
1327
|
typeAnnotation: {
|
|
1089
1328
|
type: 'TSTypeAnnotation',
|
|
1090
|
-
typeAnnotation:
|
|
1329
|
+
typeAnnotation: transformTypeAnnotationType(node.typeAnnotation)
|
|
1091
1330
|
},
|
|
1092
1331
|
optional: node.optional
|
|
1093
1332
|
};
|
|
@@ -1127,7 +1366,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1127
1366
|
const res = [];
|
|
1128
1367
|
|
|
1129
1368
|
for (const param of node.typeParameters.params) {
|
|
1130
|
-
res.push(
|
|
1369
|
+
res.push(transformTypeAnnotationType(param));
|
|
1131
1370
|
}
|
|
1132
1371
|
|
|
1133
1372
|
return res;
|
|
@@ -1166,7 +1405,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1166
1405
|
type PropType = ReturnType<ExtractPropType<Obj>>; // number
|
|
1167
1406
|
```
|
|
1168
1407
|
*/
|
|
1169
|
-
|
|
1408
|
+
return unsupportedAnnotation(node, fullTypeName);
|
|
1170
1409
|
}
|
|
1171
1410
|
|
|
1172
1411
|
case '$Diff':
|
|
@@ -1411,20 +1650,93 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1411
1650
|
} // React special conversion:
|
|
1412
1651
|
|
|
1413
1652
|
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1653
|
+
const validReactImportOrGlobal = isValidReactImportOrGlobal(baseId);
|
|
1654
|
+
const reactImport = isReactImport(baseId);
|
|
1655
|
+
|
|
1656
|
+
if (validReactImportOrGlobal || reactImport) {
|
|
1657
|
+
// Returns appropriate Identifier for `React` import.
|
|
1658
|
+
// If a global is in use, set a flag to indicate that we should add the import.
|
|
1659
|
+
const getReactIdentifier = () => {
|
|
1660
|
+
if (shouldAddReactImport !== false) {
|
|
1661
|
+
shouldAddReactImport = !reactImport;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
return {
|
|
1665
|
+
type: 'Identifier',
|
|
1666
|
+
name: `React`
|
|
1667
|
+
};
|
|
1418
1668
|
};
|
|
1419
1669
|
|
|
1420
1670
|
switch (fullTypeName) {
|
|
1671
|
+
// TODO: In flow this is `ChildrenArray<T> = T | $ReadOnlyArray<ChildrenArray<T>>`.
|
|
1672
|
+
// The recursive nature of it is rarely needed, so we're simplifying this for now
|
|
1673
|
+
// but omitting that aspect. Once we're able to provide utility types for our translations,
|
|
1674
|
+
// we should update this.
|
|
1675
|
+
// React.ChildrenArray<T> -> T | ReadonlyArray<T>
|
|
1676
|
+
// React$ChildrenArray<T> -> T | ReadonlyArray<T>
|
|
1677
|
+
case 'React.ChildrenArray':
|
|
1678
|
+
case 'React$ChildrenArray':
|
|
1679
|
+
{
|
|
1680
|
+
const [param] = assertHasExactlyNTypeParameters(1);
|
|
1681
|
+
return {
|
|
1682
|
+
type: 'TSUnionType',
|
|
1683
|
+
types: [param, {
|
|
1684
|
+
type: 'TSTypeReference',
|
|
1685
|
+
typeName: {
|
|
1686
|
+
type: 'Identifier',
|
|
1687
|
+
name: 'ReadonlyArray'
|
|
1688
|
+
},
|
|
1689
|
+
typeParameters: {
|
|
1690
|
+
type: 'TSTypeParameterInstantiation',
|
|
1691
|
+
params: [param]
|
|
1692
|
+
}
|
|
1693
|
+
}]
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
// React.Component<A,B> -> React.Component<A,B>
|
|
1697
|
+
// React$Component<A,B> -> React.Component<A,B>
|
|
1698
|
+
|
|
1699
|
+
case 'React.Component':
|
|
1700
|
+
case 'React$Component':
|
|
1701
|
+
{
|
|
1702
|
+
const typeParameters = node.typeParameters;
|
|
1703
|
+
|
|
1704
|
+
if (typeParameters == null || typeParameters.params.length === 0) {
|
|
1705
|
+
throw translationError(node, `Expected at least 1 type parameter with \`${fullTypeName}\``);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
const params = typeParameters.params;
|
|
1709
|
+
|
|
1710
|
+
if (params.length > 2) {
|
|
1711
|
+
throw translationError(node, `Expected at no more than 2 type parameters with \`${fullTypeName}\``);
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
return {
|
|
1715
|
+
type: 'TSTypeReference',
|
|
1716
|
+
typeName: {
|
|
1717
|
+
type: 'TSQualifiedName',
|
|
1718
|
+
left: getReactIdentifier(),
|
|
1719
|
+
right: {
|
|
1720
|
+
type: 'Identifier',
|
|
1721
|
+
name: 'Component'
|
|
1722
|
+
}
|
|
1723
|
+
},
|
|
1724
|
+
typeParameters: {
|
|
1725
|
+
type: 'TSTypeParameterInstantiation',
|
|
1726
|
+
params: params.map(param => transformTypeAnnotationType(param))
|
|
1727
|
+
}
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
// React.Context<A> -> React.Context<A>
|
|
1731
|
+
// React$Context<A> -> React.Context<A>
|
|
1732
|
+
|
|
1421
1733
|
case 'React$Context':
|
|
1422
1734
|
case 'React.Context':
|
|
1423
1735
|
return {
|
|
1424
1736
|
type: 'TSTypeReference',
|
|
1425
1737
|
typeName: {
|
|
1426
1738
|
type: 'TSQualifiedName',
|
|
1427
|
-
left:
|
|
1739
|
+
left: getReactIdentifier(),
|
|
1428
1740
|
right: {
|
|
1429
1741
|
type: 'Identifier',
|
|
1430
1742
|
name: `Context`
|
|
@@ -1435,6 +1747,43 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1435
1747
|
params: assertHasExactlyNTypeParameters(1)
|
|
1436
1748
|
}
|
|
1437
1749
|
};
|
|
1750
|
+
// React.Key -> React.Key
|
|
1751
|
+
// React$Key -> React.Key
|
|
1752
|
+
|
|
1753
|
+
case 'React.Key':
|
|
1754
|
+
case 'React$Key':
|
|
1755
|
+
assertHasExactlyNTypeParameters(0);
|
|
1756
|
+
return {
|
|
1757
|
+
type: 'TSTypeReference',
|
|
1758
|
+
typeName: {
|
|
1759
|
+
type: 'TSQualifiedName',
|
|
1760
|
+
left: getReactIdentifier(),
|
|
1761
|
+
right: {
|
|
1762
|
+
type: 'Identifier',
|
|
1763
|
+
name: 'Key'
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
// React.ElementType -> React.ElementType
|
|
1768
|
+
// React$ElementType -> React.ElementType
|
|
1769
|
+
|
|
1770
|
+
case 'React$ElementType':
|
|
1771
|
+
case 'React.ElementType':
|
|
1772
|
+
{
|
|
1773
|
+
assertHasExactlyNTypeParameters(0);
|
|
1774
|
+
return {
|
|
1775
|
+
type: 'TSTypeReference',
|
|
1776
|
+
typeName: {
|
|
1777
|
+
type: 'TSQualifiedName',
|
|
1778
|
+
left: getReactIdentifier(),
|
|
1779
|
+
right: {
|
|
1780
|
+
type: 'Identifier',
|
|
1781
|
+
name: `ElementType`
|
|
1782
|
+
}
|
|
1783
|
+
},
|
|
1784
|
+
typeParameters: undefined
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1438
1787
|
// React.Node -> React.ReactNode
|
|
1439
1788
|
|
|
1440
1789
|
case 'React$Node':
|
|
@@ -1445,7 +1794,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1445
1794
|
type: 'TSTypeReference',
|
|
1446
1795
|
typeName: {
|
|
1447
1796
|
type: 'TSQualifiedName',
|
|
1448
|
-
left:
|
|
1797
|
+
left: getReactIdentifier(),
|
|
1449
1798
|
right: {
|
|
1450
1799
|
type: 'Identifier',
|
|
1451
1800
|
name: `ReactNode`
|
|
@@ -1463,7 +1812,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1463
1812
|
type: 'TSTypeReference',
|
|
1464
1813
|
typeName: {
|
|
1465
1814
|
type: 'TSQualifiedName',
|
|
1466
|
-
left:
|
|
1815
|
+
left: getReactIdentifier(),
|
|
1467
1816
|
right: {
|
|
1468
1817
|
type: 'Identifier',
|
|
1469
1818
|
name: `ReactElement`
|
|
@@ -1484,7 +1833,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1484
1833
|
type: 'TSTypeReference',
|
|
1485
1834
|
typeName: {
|
|
1486
1835
|
type: 'TSQualifiedName',
|
|
1487
|
-
left:
|
|
1836
|
+
left: getReactIdentifier(),
|
|
1488
1837
|
right: {
|
|
1489
1838
|
type: 'Identifier',
|
|
1490
1839
|
name: `ElementRef`
|
|
@@ -1505,7 +1854,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1505
1854
|
type: 'TSTypeReference',
|
|
1506
1855
|
typeName: {
|
|
1507
1856
|
type: 'TSQualifiedName',
|
|
1508
|
-
left:
|
|
1857
|
+
left: getReactIdentifier(),
|
|
1509
1858
|
right: {
|
|
1510
1859
|
type: 'Identifier',
|
|
1511
1860
|
name: `Fragment`
|
|
@@ -1534,16 +1883,35 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1534
1883
|
typeParameters: undefined
|
|
1535
1884
|
};
|
|
1536
1885
|
}
|
|
1537
|
-
// React.
|
|
1538
|
-
// React
|
|
1539
|
-
// React$AbstractComponent<Config, Instance> -> React.ForwardRefExoticComponent<Config & React.RefAttributes<Instance>>
|
|
1540
|
-
// React.ComponentType<Config> -> React.ForwardRefExoticComponent<Config & React.RefAttributes<unknown>>
|
|
1541
|
-
// React$ComponentType<Config> -> React.ForwardRefExoticComponent<Config & React.RefAttributes<unknown>>
|
|
1886
|
+
// React.ComponentType<Config> -> React.ComponentType<Config>
|
|
1887
|
+
// React$ComponentType<Config> -> React.ComponentType<Config>
|
|
1542
1888
|
|
|
1543
|
-
case 'React.AbstractComponent':
|
|
1544
|
-
case 'React$AbstractComponent':
|
|
1545
1889
|
case 'React.ComponentType':
|
|
1546
1890
|
case 'React$ComponentType':
|
|
1891
|
+
{
|
|
1892
|
+
return {
|
|
1893
|
+
type: 'TSTypeReference',
|
|
1894
|
+
typeName: {
|
|
1895
|
+
type: 'TSQualifiedName',
|
|
1896
|
+
left: getReactIdentifier(),
|
|
1897
|
+
right: {
|
|
1898
|
+
type: 'Identifier',
|
|
1899
|
+
name: 'ComponentType'
|
|
1900
|
+
}
|
|
1901
|
+
},
|
|
1902
|
+
typeParameters: {
|
|
1903
|
+
type: 'TSTypeParameterInstantiation',
|
|
1904
|
+
params: assertHasExactlyNTypeParameters(1)
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
// React.AbstractComponent<Config> -> React.ComponentType<Config>
|
|
1909
|
+
// React$AbstractComponent<Config> -> React.ComponentType<Config>
|
|
1910
|
+
// React.AbstractComponent<Config, Instance> -> React.ComponentType<Config & React.RefAttributes<Instance>>
|
|
1911
|
+
// React$AbstractComponent<Config, Instance> -> React.ComponentType<Config & React.RefAttributes<Instance>>
|
|
1912
|
+
|
|
1913
|
+
case 'React.AbstractComponent':
|
|
1914
|
+
case 'React$AbstractComponent':
|
|
1547
1915
|
{
|
|
1548
1916
|
const typeParameters = node.typeParameters;
|
|
1549
1917
|
|
|
@@ -1557,49 +1925,131 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1557
1925
|
throw translationError(node, `Expected at no more than 2 type parameters with \`${fullTypeName}\``);
|
|
1558
1926
|
}
|
|
1559
1927
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1928
|
+
const newParams = (() => {
|
|
1929
|
+
if (params.length === 1) {
|
|
1930
|
+
return assertHasExactlyNTypeParameters(1);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
const [props, ref] = assertHasExactlyNTypeParameters(2);
|
|
1934
|
+
return [{
|
|
1935
|
+
type: 'TSIntersectionType',
|
|
1936
|
+
types: [props, {
|
|
1937
|
+
type: 'TSTypeReference',
|
|
1938
|
+
typeName: {
|
|
1939
|
+
type: 'TSQualifiedName',
|
|
1940
|
+
left: {
|
|
1941
|
+
type: 'Identifier',
|
|
1942
|
+
name: 'React'
|
|
1943
|
+
},
|
|
1944
|
+
right: {
|
|
1945
|
+
type: 'Identifier',
|
|
1946
|
+
name: 'RefAttributes'
|
|
1947
|
+
}
|
|
1570
1948
|
},
|
|
1571
|
-
|
|
1572
|
-
type: '
|
|
1573
|
-
|
|
1949
|
+
typeParameters: {
|
|
1950
|
+
type: 'TSTypeParameterInstantiation',
|
|
1951
|
+
params: [ref]
|
|
1574
1952
|
}
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1953
|
+
}]
|
|
1954
|
+
}];
|
|
1955
|
+
})();
|
|
1956
|
+
|
|
1957
|
+
return {
|
|
1958
|
+
type: 'TSTypeReference',
|
|
1959
|
+
typeName: {
|
|
1960
|
+
type: 'TSQualifiedName',
|
|
1961
|
+
left: getReactIdentifier(),
|
|
1962
|
+
right: {
|
|
1963
|
+
type: 'Identifier',
|
|
1964
|
+
name: 'ComponentType'
|
|
1581
1965
|
}
|
|
1582
|
-
}
|
|
1966
|
+
},
|
|
1967
|
+
typeParameters: {
|
|
1968
|
+
type: 'TSTypeParameterInstantiation',
|
|
1969
|
+
params: newParams
|
|
1970
|
+
}
|
|
1583
1971
|
};
|
|
1972
|
+
}
|
|
1973
|
+
// React.ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
|
|
1974
|
+
// React$ElementConfig<A> -> JSX.LibraryManagedAttributes<A, React.ComponentProps<A>>
|
|
1975
|
+
|
|
1976
|
+
case 'React.ElementConfig':
|
|
1977
|
+
case 'React$ElementConfig':
|
|
1978
|
+
{
|
|
1979
|
+
const [param] = assertHasExactlyNTypeParameters(1);
|
|
1584
1980
|
return {
|
|
1585
1981
|
type: 'TSTypeReference',
|
|
1586
1982
|
typeName: {
|
|
1587
1983
|
type: 'TSQualifiedName',
|
|
1588
|
-
left:
|
|
1984
|
+
left: {
|
|
1985
|
+
type: 'Identifier',
|
|
1986
|
+
name: 'JSX'
|
|
1987
|
+
},
|
|
1589
1988
|
right: {
|
|
1590
1989
|
type: 'Identifier',
|
|
1591
|
-
name:
|
|
1990
|
+
name: 'LibraryManagedAttributes'
|
|
1592
1991
|
}
|
|
1593
1992
|
},
|
|
1594
1993
|
typeParameters: {
|
|
1595
1994
|
type: 'TSTypeParameterInstantiation',
|
|
1596
|
-
params: [
|
|
1995
|
+
params: [param, {
|
|
1996
|
+
type: 'TSTypeReference',
|
|
1997
|
+
typeName: {
|
|
1998
|
+
type: 'TSQualifiedName',
|
|
1999
|
+
left: getReactIdentifier(),
|
|
2000
|
+
right: {
|
|
2001
|
+
type: 'Identifier',
|
|
2002
|
+
name: `ComponentProps`
|
|
2003
|
+
}
|
|
2004
|
+
},
|
|
2005
|
+
typeParameters: {
|
|
2006
|
+
type: 'TSTypeParameterInstantiation',
|
|
2007
|
+
params: [param]
|
|
2008
|
+
}
|
|
2009
|
+
}]
|
|
1597
2010
|
}
|
|
1598
2011
|
};
|
|
1599
2012
|
}
|
|
2013
|
+
// React.Ref<C> -> NonNullable<React.Ref<C> | string | number>
|
|
2014
|
+
// React$Ref<C> -> NonNullable<React.Ref<C> | string | number>
|
|
2015
|
+
|
|
2016
|
+
case 'React.Ref':
|
|
2017
|
+
case 'React$Ref':
|
|
2018
|
+
return {
|
|
2019
|
+
type: 'TSTypeReference',
|
|
2020
|
+
typeName: {
|
|
2021
|
+
type: 'Identifier',
|
|
2022
|
+
name: 'NonNullable'
|
|
2023
|
+
},
|
|
2024
|
+
typeParameters: {
|
|
2025
|
+
type: 'TSTypeParameterInstantiation',
|
|
2026
|
+
params: [{
|
|
2027
|
+
type: 'TSUnionType',
|
|
2028
|
+
types: [{
|
|
2029
|
+
type: 'TSTypeReference',
|
|
2030
|
+
typeName: {
|
|
2031
|
+
type: 'TSQualifiedName',
|
|
2032
|
+
left: getReactIdentifier(),
|
|
2033
|
+
right: {
|
|
2034
|
+
type: 'Identifier',
|
|
2035
|
+
name: 'Ref'
|
|
2036
|
+
}
|
|
2037
|
+
},
|
|
2038
|
+
typeParameters: {
|
|
2039
|
+
type: 'TSTypeParameterInstantiation',
|
|
2040
|
+
params: assertHasExactlyNTypeParameters(1)
|
|
2041
|
+
}
|
|
2042
|
+
}, {
|
|
2043
|
+
type: 'TSStringKeyword'
|
|
2044
|
+
}, {
|
|
2045
|
+
type: 'TSNumberKeyword'
|
|
2046
|
+
}]
|
|
2047
|
+
}]
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
1600
2050
|
|
|
1601
2051
|
default:
|
|
1602
|
-
|
|
2052
|
+
return unsupportedAnnotation(node, fullTypeName);
|
|
1603
2053
|
}
|
|
1604
2054
|
}
|
|
1605
2055
|
|
|
@@ -1623,8 +2073,8 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1623
2073
|
IndexedAccessType(node) {
|
|
1624
2074
|
return {
|
|
1625
2075
|
type: 'TSIndexedAccessType',
|
|
1626
|
-
objectType:
|
|
1627
|
-
indexType:
|
|
2076
|
+
objectType: transformTypeAnnotationType(node.objectType),
|
|
2077
|
+
indexType: transformTypeAnnotationType(node.indexType)
|
|
1628
2078
|
};
|
|
1629
2079
|
},
|
|
1630
2080
|
|
|
@@ -1641,63 +2091,63 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1641
2091
|
},
|
|
1642
2092
|
|
|
1643
2093
|
ImportDeclaration(node) {
|
|
1644
|
-
if (node.importKind === 'typeof') {
|
|
1645
|
-
/*
|
|
1646
|
-
TODO - this is a complicated change to support because TS
|
|
1647
|
-
does not have typeof imports.
|
|
1648
|
-
Making it a `type` import would change the meaning!
|
|
1649
|
-
The only way to truly support this is to prefix all **usages** with `typeof T`.
|
|
1650
|
-
eg:
|
|
1651
|
-
```
|
|
1652
|
-
import typeof Foo from 'Foo';
|
|
1653
|
-
type T = Foo;
|
|
1654
|
-
```
|
|
1655
|
-
would become:
|
|
1656
|
-
```
|
|
1657
|
-
import type Foo from 'Foo';
|
|
1658
|
-
type T = typeof Foo;
|
|
1659
|
-
```
|
|
1660
|
-
This seems simple, but will actually be super complicated for us to do with
|
|
1661
|
-
our current translation architecture
|
|
1662
|
-
*/
|
|
1663
|
-
throw unsupportedTranslationError(node, 'typeof imports');
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
2094
|
const importKind = node.importKind;
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
2095
|
+
const specifiers = [];
|
|
2096
|
+
const unsupportedSpecifiers = [];
|
|
2097
|
+
node.specifiers.forEach(spec => {
|
|
2098
|
+
let id = (() => {
|
|
2099
|
+
if (node.importKind === 'typeof' || spec.importKind === 'typeof') {
|
|
2100
|
+
const id = {
|
|
2101
|
+
type: 'Identifier',
|
|
2102
|
+
name: getPlaceholderNameForTypeofImport()
|
|
2103
|
+
};
|
|
2104
|
+
unsupportedSpecifiers.push({
|
|
2105
|
+
type: 'TSTypeAliasDeclaration',
|
|
2106
|
+
id: transform.Identifier(spec.local, false),
|
|
2107
|
+
typeAnnotation: {
|
|
2108
|
+
type: 'TSTypeQuery',
|
|
2109
|
+
exprName: id
|
|
2110
|
+
}
|
|
2111
|
+
});
|
|
2112
|
+
return id;
|
|
2113
|
+
}
|
|
1679
2114
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
type: 'ImportNamespaceSpecifier',
|
|
1683
|
-
local: transform.Identifier(spec.local, false)
|
|
1684
|
-
};
|
|
2115
|
+
return transform.Identifier(spec.local, false);
|
|
2116
|
+
})();
|
|
1685
2117
|
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
2118
|
+
switch (spec.type) {
|
|
2119
|
+
case 'ImportDefaultSpecifier':
|
|
2120
|
+
specifiers.push({
|
|
2121
|
+
type: 'ImportDefaultSpecifier',
|
|
2122
|
+
local: id
|
|
2123
|
+
});
|
|
2124
|
+
return;
|
|
1691
2125
|
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
2126
|
+
case 'ImportNamespaceSpecifier':
|
|
2127
|
+
specifiers.push({
|
|
2128
|
+
type: 'ImportNamespaceSpecifier',
|
|
2129
|
+
local: id
|
|
2130
|
+
});
|
|
2131
|
+
return;
|
|
2132
|
+
|
|
2133
|
+
case 'ImportSpecifier':
|
|
2134
|
+
specifiers.push({
|
|
2135
|
+
type: 'ImportSpecifier',
|
|
2136
|
+
importKind: spec.importKind === 'typeof' || spec.importKind === 'type' ? 'type' : null,
|
|
2137
|
+
imported: transform.Identifier(spec.imported, false),
|
|
2138
|
+
local: id
|
|
2139
|
+
});
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
});
|
|
2143
|
+
const out = specifiers.length ? [{
|
|
2144
|
+
type: 'ImportDeclaration',
|
|
2145
|
+
assertions: node.assertions.map(transform.ImportAttribute),
|
|
2146
|
+
importKind: importKind === 'typeof' ? 'type' : importKind != null ? importKind : 'value',
|
|
2147
|
+
source: transform.StringLiteral(node.source),
|
|
2148
|
+
specifiers
|
|
2149
|
+
}] : [];
|
|
2150
|
+
return [...out, ...unsupportedSpecifiers];
|
|
1701
2151
|
},
|
|
1702
2152
|
|
|
1703
2153
|
InterfaceExtends(node) {
|
|
@@ -1729,7 +2179,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1729
2179
|
IntersectionTypeAnnotation(node) {
|
|
1730
2180
|
return {
|
|
1731
2181
|
type: 'TSIntersectionType',
|
|
1732
|
-
types: node.types.map(
|
|
2182
|
+
types: node.types.map(transformTypeAnnotationType)
|
|
1733
2183
|
};
|
|
1734
2184
|
},
|
|
1735
2185
|
|
|
@@ -1784,7 +2234,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1784
2234
|
type: 'TSNullKeyword'
|
|
1785
2235
|
}, {
|
|
1786
2236
|
type: 'TSUndefinedKeyword'
|
|
1787
|
-
},
|
|
2237
|
+
}, transformTypeAnnotationType(node.typeAnnotation)]
|
|
1788
2238
|
};
|
|
1789
2239
|
},
|
|
1790
2240
|
|
|
@@ -1841,7 +2291,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1841
2291
|
|
|
1842
2292
|
|
|
1843
2293
|
if (node.internalSlots.length > 0) {
|
|
1844
|
-
|
|
2294
|
+
return unsupportedAnnotation(node.internalSlots[0], 'internal slots');
|
|
1845
2295
|
}
|
|
1846
2296
|
|
|
1847
2297
|
if (!node.properties.find(FlowESTree.isObjectTypeSpreadProperty)) {
|
|
@@ -1852,6 +2302,11 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1852
2302
|
throw unexpectedTranslationError(property, 'Impossible state');
|
|
1853
2303
|
}
|
|
1854
2304
|
|
|
2305
|
+
if (property.type === 'ObjectTypeMappedTypeProperty') {
|
|
2306
|
+
// TODO - Support mapped types
|
|
2307
|
+
return unsupportedAnnotation(property, 'object type with mapped type property');
|
|
2308
|
+
}
|
|
2309
|
+
|
|
1855
2310
|
members.push({
|
|
1856
2311
|
start: property.range[0],
|
|
1857
2312
|
node: transform.ObjectTypeProperty(property)
|
|
@@ -1928,7 +2383,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1928
2383
|
- spreads of things that aren't "Identifiers"
|
|
1929
2384
|
*/
|
|
1930
2385
|
if (members.length > 0) {
|
|
1931
|
-
|
|
2386
|
+
return unsupportedAnnotation(node, 'object types with spreads, indexers and/or call properties at the same time');
|
|
1932
2387
|
}
|
|
1933
2388
|
|
|
1934
2389
|
const typesToIntersect = [];
|
|
@@ -1936,16 +2391,19 @@ const getTransforms = (code, scopeManager) => {
|
|
|
1936
2391
|
for (const property of node.properties) {
|
|
1937
2392
|
if (property.type === 'ObjectTypeSpreadProperty') {
|
|
1938
2393
|
if (members.length > 0) {
|
|
1939
|
-
|
|
2394
|
+
return unsupportedAnnotation(property, 'object types with spreads in the middle or at the end');
|
|
1940
2395
|
}
|
|
1941
2396
|
|
|
1942
|
-
const spreadType =
|
|
2397
|
+
const spreadType = transformTypeAnnotationType(property.argument);
|
|
1943
2398
|
|
|
1944
2399
|
if (spreadType.type !== 'TSTypeReference') {
|
|
1945
|
-
|
|
2400
|
+
return unsupportedAnnotation(property, 'object types with complex spreads');
|
|
1946
2401
|
}
|
|
1947
2402
|
|
|
1948
2403
|
typesToIntersect.push(spreadType);
|
|
2404
|
+
} else if (property.type === 'ObjectTypeMappedTypeProperty') {
|
|
2405
|
+
// TODO - Support mapped types
|
|
2406
|
+
return unsupportedAnnotation(property, 'object type with mapped type property');
|
|
1949
2407
|
} else {
|
|
1950
2408
|
members.push({
|
|
1951
2409
|
start: property.range[0],
|
|
@@ -2015,14 +2473,14 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2015
2473
|
name: node.id == null ? '$$Key$$' : node.id.name,
|
|
2016
2474
|
typeAnnotation: {
|
|
2017
2475
|
type: 'TSTypeAnnotation',
|
|
2018
|
-
typeAnnotation:
|
|
2476
|
+
typeAnnotation: transformTypeAnnotationType(node.key)
|
|
2019
2477
|
}
|
|
2020
2478
|
}],
|
|
2021
2479
|
readonly: ((_node$variance = node.variance) == null ? void 0 : _node$variance.kind) === 'plus',
|
|
2022
2480
|
static: node.static,
|
|
2023
2481
|
typeAnnotation: {
|
|
2024
2482
|
type: 'TSTypeAnnotation',
|
|
2025
|
-
typeAnnotation:
|
|
2483
|
+
typeAnnotation: transformTypeAnnotationType(node.value)
|
|
2026
2484
|
}
|
|
2027
2485
|
};
|
|
2028
2486
|
},
|
|
@@ -2077,7 +2535,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2077
2535
|
static: node.static,
|
|
2078
2536
|
typeAnnotation: {
|
|
2079
2537
|
type: 'TSTypeAnnotation',
|
|
2080
|
-
typeAnnotation:
|
|
2538
|
+
typeAnnotation: transformTypeAnnotationType(node.value)
|
|
2081
2539
|
}
|
|
2082
2540
|
};
|
|
2083
2541
|
},
|
|
@@ -2106,10 +2564,10 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2106
2564
|
},
|
|
2107
2565
|
typeParameters: {
|
|
2108
2566
|
type: 'TSTypeParameterInstantiation',
|
|
2109
|
-
params: [
|
|
2567
|
+
params: [transformTypeAnnotationType(node.objectType)]
|
|
2110
2568
|
}
|
|
2111
2569
|
},
|
|
2112
|
-
indexType:
|
|
2570
|
+
indexType: transformTypeAnnotationType(node.indexType)
|
|
2113
2571
|
};
|
|
2114
2572
|
},
|
|
2115
2573
|
|
|
@@ -2122,6 +2580,15 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2122
2580
|
};
|
|
2123
2581
|
},
|
|
2124
2582
|
|
|
2583
|
+
QualifiedTypeofIdentifier(node) {
|
|
2584
|
+
const qual = node.qualification;
|
|
2585
|
+
return {
|
|
2586
|
+
type: 'TSQualifiedName',
|
|
2587
|
+
left: qual.type === 'Identifier' ? transform.Identifier(qual, false) : transform.QualifiedTypeofIdentifier(qual),
|
|
2588
|
+
right: transform.Identifier(node.id, false)
|
|
2589
|
+
};
|
|
2590
|
+
},
|
|
2591
|
+
|
|
2125
2592
|
RegExpLiteral(node) {
|
|
2126
2593
|
return {
|
|
2127
2594
|
type: 'Literal',
|
|
@@ -2174,7 +2641,7 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2174
2641
|
TupleTypeAnnotation(node) {
|
|
2175
2642
|
return {
|
|
2176
2643
|
type: 'TSTupleType',
|
|
2177
|
-
elementTypes: node.types.map(
|
|
2644
|
+
elementTypes: node.types.map(transformTypeAnnotationType)
|
|
2178
2645
|
};
|
|
2179
2646
|
},
|
|
2180
2647
|
|
|
@@ -2185,116 +2652,26 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2185
2652
|
TypeAnnotation(node) {
|
|
2186
2653
|
return {
|
|
2187
2654
|
type: 'TSTypeAnnotation',
|
|
2188
|
-
typeAnnotation:
|
|
2655
|
+
typeAnnotation: transformTypeAnnotationType(node.typeAnnotation)
|
|
2189
2656
|
};
|
|
2190
2657
|
},
|
|
2191
2658
|
|
|
2192
|
-
TypeAnnotationType(node) {
|
|
2193
|
-
switch (node.type) {
|
|
2194
|
-
case 'AnyTypeAnnotation':
|
|
2195
|
-
return transform.AnyTypeAnnotation(node);
|
|
2196
|
-
|
|
2197
|
-
case 'ArrayTypeAnnotation':
|
|
2198
|
-
return transform.ArrayTypeAnnotation(node);
|
|
2199
|
-
|
|
2200
|
-
case 'BigIntLiteralTypeAnnotation':
|
|
2201
|
-
return transform.BigIntLiteralTypeAnnotation(node);
|
|
2202
|
-
|
|
2203
|
-
case 'BigIntTypeAnnotation':
|
|
2204
|
-
return transform.BigIntTypeAnnotation(node);
|
|
2205
|
-
|
|
2206
|
-
case 'BooleanLiteralTypeAnnotation':
|
|
2207
|
-
return transform.BooleanLiteralTypeAnnotation(node);
|
|
2208
|
-
|
|
2209
|
-
case 'BooleanTypeAnnotation':
|
|
2210
|
-
return transform.BooleanTypeAnnotation(node);
|
|
2211
|
-
|
|
2212
|
-
case 'EmptyTypeAnnotation':
|
|
2213
|
-
return transform.EmptyTypeAnnotation(node);
|
|
2214
|
-
|
|
2215
|
-
case 'ExistsTypeAnnotation':
|
|
2216
|
-
return transform.ExistsTypeAnnotation(node);
|
|
2217
|
-
|
|
2218
|
-
case 'FunctionTypeAnnotation':
|
|
2219
|
-
return transform.FunctionTypeAnnotation(node);
|
|
2220
|
-
|
|
2221
|
-
case 'GenericTypeAnnotation':
|
|
2222
|
-
return transform.GenericTypeAnnotation(node);
|
|
2223
|
-
|
|
2224
|
-
case 'IndexedAccessType':
|
|
2225
|
-
return transform.IndexedAccessType(node);
|
|
2226
|
-
|
|
2227
|
-
case 'InterfaceTypeAnnotation':
|
|
2228
|
-
return transform.InterfaceTypeAnnotation(node);
|
|
2229
|
-
|
|
2230
|
-
case 'IntersectionTypeAnnotation':
|
|
2231
|
-
return transform.IntersectionTypeAnnotation(node);
|
|
2232
|
-
|
|
2233
|
-
case 'MixedTypeAnnotation':
|
|
2234
|
-
return transform.MixedTypeAnnotation(node);
|
|
2235
|
-
|
|
2236
|
-
case 'NullLiteralTypeAnnotation':
|
|
2237
|
-
return transform.NullLiteralTypeAnnotation(node);
|
|
2238
|
-
|
|
2239
|
-
case 'NullableTypeAnnotation':
|
|
2240
|
-
return transform.NullableTypeAnnotation(node);
|
|
2241
|
-
|
|
2242
|
-
case 'NumberLiteralTypeAnnotation':
|
|
2243
|
-
return transform.NumberLiteralTypeAnnotation(node);
|
|
2244
|
-
|
|
2245
|
-
case 'NumberTypeAnnotation':
|
|
2246
|
-
return transform.NumberTypeAnnotation(node);
|
|
2247
|
-
|
|
2248
|
-
case 'ObjectTypeAnnotation':
|
|
2249
|
-
return transform.ObjectTypeAnnotation(node);
|
|
2250
|
-
|
|
2251
|
-
case 'OptionalIndexedAccessType':
|
|
2252
|
-
return transform.OptionalIndexedAccessType(node);
|
|
2253
|
-
|
|
2254
|
-
case 'QualifiedTypeIdentifier':
|
|
2255
|
-
return transform.QualifiedTypeIdentifier(node);
|
|
2256
|
-
|
|
2257
|
-
case 'StringLiteralTypeAnnotation':
|
|
2258
|
-
return transform.StringLiteralTypeAnnotation(node);
|
|
2259
|
-
|
|
2260
|
-
case 'StringTypeAnnotation':
|
|
2261
|
-
return transform.StringTypeAnnotation(node);
|
|
2262
|
-
|
|
2263
|
-
case 'SymbolTypeAnnotation':
|
|
2264
|
-
return transform.SymbolTypeAnnotation(node);
|
|
2265
|
-
|
|
2266
|
-
case 'ThisTypeAnnotation':
|
|
2267
|
-
return transform.ThisTypeAnnotation(node);
|
|
2268
|
-
|
|
2269
|
-
case 'TupleTypeAnnotation':
|
|
2270
|
-
return transform.TupleTypeAnnotation(node);
|
|
2271
|
-
|
|
2272
|
-
case 'TypeofTypeAnnotation':
|
|
2273
|
-
return transform.TypeofTypeAnnotation(node);
|
|
2274
|
-
|
|
2275
|
-
case 'UnionTypeAnnotation':
|
|
2276
|
-
return transform.UnionTypeAnnotation(node);
|
|
2277
|
-
|
|
2278
|
-
case 'VoidTypeAnnotation':
|
|
2279
|
-
return transform.VoidTypeAnnotation(node);
|
|
2280
|
-
|
|
2281
|
-
default:
|
|
2282
|
-
throw unexpectedTranslationError(node, `Unhandled type ${node.type}`);
|
|
2283
|
-
}
|
|
2284
|
-
},
|
|
2285
|
-
|
|
2286
2659
|
TypeofTypeAnnotation(node) {
|
|
2287
|
-
|
|
2660
|
+
switch (node.argument.type) {
|
|
2661
|
+
case 'Identifier':
|
|
2662
|
+
return {
|
|
2663
|
+
type: 'TSTypeQuery',
|
|
2664
|
+
exprName: transform.Identifier(node.argument),
|
|
2665
|
+
typeParameters: undefined
|
|
2666
|
+
};
|
|
2288
2667
|
|
|
2289
|
-
|
|
2290
|
-
|
|
2668
|
+
case 'QualifiedTypeofIdentifier':
|
|
2669
|
+
return {
|
|
2670
|
+
type: 'TSTypeQuery',
|
|
2671
|
+
exprName: transform.QualifiedTypeofIdentifier(node.argument),
|
|
2672
|
+
typeParameters: undefined
|
|
2673
|
+
};
|
|
2291
2674
|
}
|
|
2292
|
-
|
|
2293
|
-
return {
|
|
2294
|
-
type: 'TSTypeQuery',
|
|
2295
|
-
exprName: argument.typeName,
|
|
2296
|
-
typeParameters: argument.typeParameters
|
|
2297
|
-
};
|
|
2298
2675
|
},
|
|
2299
2676
|
|
|
2300
2677
|
TypeParameter(node) {
|
|
@@ -2323,8 +2700,8 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2323
2700
|
type: 'Identifier',
|
|
2324
2701
|
name: node.name
|
|
2325
2702
|
},
|
|
2326
|
-
constraint: node.bound == null ? undefined :
|
|
2327
|
-
default: node.default == null ? undefined :
|
|
2703
|
+
constraint: node.bound == null ? undefined : transformTypeAnnotationType(node.bound.typeAnnotation),
|
|
2704
|
+
default: node.default == null ? undefined : transformTypeAnnotationType(node.default),
|
|
2328
2705
|
in: false,
|
|
2329
2706
|
out: false // in: variance.has('in'),
|
|
2330
2707
|
// out: variance.has('out'),
|
|
@@ -2342,14 +2719,14 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2342
2719
|
TypeParameterInstantiation(node) {
|
|
2343
2720
|
return {
|
|
2344
2721
|
type: 'TSTypeParameterInstantiation',
|
|
2345
|
-
params: node.params.map(
|
|
2722
|
+
params: node.params.map(transformTypeAnnotationType)
|
|
2346
2723
|
};
|
|
2347
2724
|
},
|
|
2348
2725
|
|
|
2349
2726
|
UnionTypeAnnotation(node) {
|
|
2350
2727
|
return {
|
|
2351
2728
|
type: 'TSUnionType',
|
|
2352
|
-
types: node.types.map(
|
|
2729
|
+
types: node.types.map(transformTypeAnnotationType)
|
|
2353
2730
|
};
|
|
2354
2731
|
},
|
|
2355
2732
|
|
|
@@ -2379,5 +2756,5 @@ const getTransforms = (code, scopeManager) => {
|
|
|
2379
2756
|
};
|
|
2380
2757
|
}
|
|
2381
2758
|
|
|
2382
|
-
return transform;
|
|
2759
|
+
return [transform, code];
|
|
2383
2760
|
};
|