diff --git a/packages/core/integration-tests/test/ts-types.js b/packages/core/integration-tests/test/ts-types.js
index c09d989dc9e..9d26b4cab47 100644
--- a/packages/core/integration-tests/test/ts-types.js
+++ b/packages/core/integration-tests/test/ts-types.js
@@ -466,6 +466,7 @@ describe('typescript types', function () {
index.ts:
export * from "./ErrorBoundary";
export * from "./ErrorBoundaryContext";
+ export * from "./Component";
foo.js:
import {baz} from './baz';
@@ -495,6 +496,11 @@ describe('typescript types', function () {
);
}
}
+
+ Component.tsx:
+ export function Foo() {
+ return
Foo
;
+ }
`;
let b = await bundle(path.join(dir, '/index.ts'), {
@@ -505,12 +511,13 @@ describe('typescript types', function () {
let output = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');
assert.equal(
output,
- `import { Context, Component, PropsWithChildren, ProviderProps, FunctionComponentElement } from "react";
+ `import { Context, Component, PropsWithChildren, ProviderProps, FunctionComponentElement, JSX } from "react";
export type ErrorBoundaryContextType = {};
export const ErrorBoundaryContext: Context;
export class ErrorBoundary extends Component {
render(): FunctionComponentElement>;
}
+export function Foo(): JSX.Element;
//# sourceMappingURL=types.d.ts.map
`,
diff --git a/packages/transformers/typescript-types/src/collect.js b/packages/transformers/typescript-types/src/collect.js
index eddf82f3338..5beaab0d143 100644
--- a/packages/transformers/typescript-types/src/collect.js
+++ b/packages/transformers/typescript-types/src/collect.js
@@ -2,7 +2,7 @@
import type {TSModuleGraph} from './TSModuleGraph';
import nullthrows from 'nullthrows';
-import ts from 'typescript';
+import ts, {type EntityName} from 'typescript';
import {TSModule} from './TSModule';
import {getExportedName, isDeclaration} from './utils';
@@ -91,16 +91,9 @@ export function collect(
ts.isStringLiteral(node.argument.literal)
) {
let local = `$$parcel$import$${moduleGraph.syntheticImportCount++}`;
- if (node.qualifier) {
- currentModule.addImport(
- local,
- node.argument.literal.text,
- node.qualifier.text,
- );
- } else {
- currentModule.addImport(local, node.argument.literal.text, '*');
- }
- return factory.createTypeReferenceNode(local, node.typeArguments);
+ let [specifier, entity] = getImportName(node.qualifier, local, factory);
+ currentModule.addImport(local, node.argument.literal.text, specifier);
+ return factory.createTypeReferenceNode(entity, node.typeArguments);
}
// Handle `export default name;`
@@ -142,3 +135,23 @@ export function collect(
return ts.visitNode(sourceFile, visit);
}
+
+// Traverse down an EntityName to the root identifier. Return that to use as the named import specifier,
+// and collect the remaining parts into a new QualifiedName with the local replacement at the root.
+// import('react').JSX.Element => import {JSX} from 'react'; JSX.Element
+function getImportName(
+ qualifier: ?EntityName,
+ local: string,
+ factory: typeof ts,
+) {
+ if (!qualifier) {
+ return ['*', factory.createIdentifier(local)];
+ }
+
+ if (qualifier.kind === ts.SyntaxKind.Identifier) {
+ return [qualifier.text, factory.createIdentifier(local)];
+ }
+
+ let [name, entity] = getImportName(qualifier.left, local, factory);
+ return [name, factory.createQualifiedName(entity, qualifier.right)];
+}