Skip to content

Commit aeaba41

Browse files
authored
Handle dynamic import type references in TS types transformer (#9573)
1 parent a2cf988 commit aeaba41

File tree

5 files changed

+114
-2
lines changed

5 files changed

+114
-2
lines changed

packages/core/integration-tests/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@babel/preset-typescript": "^7.22.11",
2222
"@jetbrains/kotlinc-js-api": "^1.2.12",
2323
"@mdx-js/react": "^1.5.3",
24+
"@types/react": "^17",
2425
"autoprefixer": "^10.4.0",
2526
"chalk": "^4.1.0",
2627
"command-exists": "^1.2.6",

packages/core/integration-tests/test/ts-types.js

+66
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
overlayFS,
88
outputFS,
99
ncp,
10+
fsFixture,
1011
} from '@parcel/test-utils';
1112
import {md} from '@parcel/diagnostic';
1213
import {normalizeSeparators} from '@parcel/utils';
@@ -450,4 +451,69 @@ describe('typescript types', function () {
450451
);
451452
assert.equal(dist, expected);
452453
});
454+
455+
it('should handle dynamic imports generated by TS', async function () {
456+
let dir = __dirname + '/dynamic-import-ts';
457+
await overlayFS.mkdirp(dir);
458+
await fsFixture(overlayFS, dir)`
459+
yarn.lock:
460+
461+
package.json:
462+
{
463+
"types": "dist/types.d.ts"
464+
}
465+
466+
index.ts:
467+
export * from "./ErrorBoundary";
468+
export * from "./ErrorBoundaryContext";
469+
470+
foo.js:
471+
import {baz} from './baz';
472+
export function foo() {
473+
return 'foo' + baz();
474+
}
475+
476+
ErrorBoundaryContext.ts:
477+
import { createContext } from "react";
478+
export type ErrorBoundaryContextType = {};
479+
export const ErrorBoundaryContext = createContext<ErrorBoundaryContextType | null>(null);
480+
481+
ErrorBoundary.ts:
482+
import { Component, createElement, PropsWithChildren } from "react";
483+
import { ErrorBoundaryContext } from "./ErrorBoundaryContext";
484+
485+
export class ErrorBoundary extends Component<PropsWithChildren> {
486+
render() {
487+
const { children } = this.props;
488+
489+
return createElement(
490+
ErrorBoundaryContext.Provider,
491+
{
492+
value: {},
493+
},
494+
children
495+
);
496+
}
497+
}
498+
`;
499+
500+
let b = await bundle(path.join(dir, '/index.ts'), {
501+
inputFS: overlayFS,
502+
mode: 'production',
503+
});
504+
505+
let output = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');
506+
assert.equal(
507+
output,
508+
`import { Context, Component, PropsWithChildren, ProviderProps, FunctionComponentElement } from "react";
509+
export type ErrorBoundaryContextType = {};
510+
export const ErrorBoundaryContext: Context<ErrorBoundaryContextType>;
511+
export class ErrorBoundary extends Component<PropsWithChildren> {
512+
render(): FunctionComponentElement<ProviderProps<ErrorBoundaryContextType>>;
513+
}
514+
515+
//# sourceMappingURL=types.d.ts.map
516+
`,
517+
);
518+
});
453519
});

packages/transformers/typescript-types/src/TSModuleGraph.js

+2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ export class TSModuleGraph {
99
modules: Map<string, TSModule>;
1010
mainModuleName: string;
1111
mainModule: ?TSModule;
12+
syntheticImportCount: number;
1213

1314
constructor(mainModuleName: string) {
1415
this.modules = new Map();
1516
this.mainModuleName = mainModuleName;
1617
this.mainModule = null;
18+
this.syntheticImportCount = 0;
1719
}
1820

1921
addModule(name: string, module: TSModule) {

packages/transformers/typescript-types/src/collect.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@ export function collect(
8383
}
8484
}
8585

86+
node = ts.visitEachChild(node, visit, context);
87+
88+
if (
89+
ts.isImportTypeNode(node) &&
90+
ts.isLiteralTypeNode(node.argument) &&
91+
ts.isStringLiteral(node.argument.literal)
92+
) {
93+
let local = `$$parcel$import$${moduleGraph.syntheticImportCount++}`;
94+
if (node.qualifier) {
95+
currentModule.addImport(
96+
local,
97+
node.argument.literal.text,
98+
node.qualifier.text,
99+
);
100+
} else {
101+
currentModule.addImport(local, node.argument.literal.text, '*');
102+
}
103+
return factory.createTypeReferenceNode(local, node.typeArguments);
104+
}
105+
86106
// Handle `export default name;`
87107
if (ts.isExportAssignment(node) && ts.isIdentifier(node.expression)) {
88108
currentModule.addExport('default', node.expression.text);
@@ -112,13 +132,12 @@ export function collect(
112132
}
113133
}
114134

115-
const results = ts.visitEachChild(node, visit, context);
116135
// After we finish traversing the children of a module definition,
117136
// we need to make sure that subsequent nodes get associated with the next-highest level module.
118137
if (ts.isModuleDeclaration(node)) {
119138
_currentModule = moduleStack.pop();
120139
}
121-
return results;
140+
return node;
122141
};
123142

124143
return ts.visitNode(sourceFile, visit);

yarn.lock

+24
Original file line numberDiff line numberDiff line change
@@ -2641,6 +2641,25 @@
26412641
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
26422642
integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==
26432643

2644+
"@types/prop-types@*":
2645+
version "15.7.11"
2646+
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
2647+
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
2648+
2649+
"@types/react@^17":
2650+
version "17.0.76"
2651+
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.76.tgz#bfdf762046699e265655cd8f67a51beab6cd1e80"
2652+
integrity sha512-w9Aq+qeszGYoQM0hgFcdsAODGJdogadBDiitPm+zjBFJ0mLymvn2qSXsDaLJUndFRqqXk1FQfa9avHUBk1JhJQ==
2653+
dependencies:
2654+
"@types/prop-types" "*"
2655+
"@types/scheduler" "*"
2656+
csstype "^3.0.2"
2657+
2658+
"@types/scheduler@*":
2659+
version "0.16.8"
2660+
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
2661+
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
2662+
26442663
"@types/semver@^7.3.12":
26452664
version "7.5.0"
26462665
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
@@ -5037,6 +5056,11 @@ csstype@^2.6.8:
50375056
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5"
50385057
integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==
50395058

5059+
csstype@^3.0.2:
5060+
version "3.1.3"
5061+
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
5062+
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
5063+
50405064
csstype@^3.0.6:
50415065
version "3.1.2"
50425066
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"

0 commit comments

Comments
 (0)