Skip to content

Commit

Permalink
Handle dynamic import type references in TS types transformer (#9573)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett authored Mar 11, 2024
1 parent a2cf988 commit aeaba41
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/core/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@babel/preset-typescript": "^7.22.11",
"@jetbrains/kotlinc-js-api": "^1.2.12",
"@mdx-js/react": "^1.5.3",
"@types/react": "^17",
"autoprefixer": "^10.4.0",
"chalk": "^4.1.0",
"command-exists": "^1.2.6",
Expand Down
66 changes: 66 additions & 0 deletions packages/core/integration-tests/test/ts-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
overlayFS,
outputFS,
ncp,
fsFixture,
} from '@parcel/test-utils';
import {md} from '@parcel/diagnostic';
import {normalizeSeparators} from '@parcel/utils';
Expand Down Expand Up @@ -450,4 +451,69 @@ describe('typescript types', function () {
);
assert.equal(dist, expected);
});

it('should handle dynamic imports generated by TS', async function () {
let dir = __dirname + '/dynamic-import-ts';
await overlayFS.mkdirp(dir);
await fsFixture(overlayFS, dir)`
yarn.lock:
package.json:
{
"types": "dist/types.d.ts"
}
index.ts:
export * from "./ErrorBoundary";
export * from "./ErrorBoundaryContext";
foo.js:
import {baz} from './baz';
export function foo() {
return 'foo' + baz();
}
ErrorBoundaryContext.ts:
import { createContext } from "react";
export type ErrorBoundaryContextType = {};
export const ErrorBoundaryContext = createContext<ErrorBoundaryContextType | null>(null);
ErrorBoundary.ts:
import { Component, createElement, PropsWithChildren } from "react";
import { ErrorBoundaryContext } from "./ErrorBoundaryContext";
export class ErrorBoundary extends Component<PropsWithChildren> {
render() {
const { children } = this.props;
return createElement(
ErrorBoundaryContext.Provider,
{
value: {},
},
children
);
}
}
`;

let b = await bundle(path.join(dir, '/index.ts'), {
inputFS: overlayFS,
mode: 'production',
});

let output = await outputFS.readFile(b.getBundles()[0].filePath, 'utf8');
assert.equal(
output,
`import { Context, Component, PropsWithChildren, ProviderProps, FunctionComponentElement } from "react";
export type ErrorBoundaryContextType = {};
export const ErrorBoundaryContext: Context<ErrorBoundaryContextType>;
export class ErrorBoundary extends Component<PropsWithChildren> {
render(): FunctionComponentElement<ProviderProps<ErrorBoundaryContextType>>;
}
//# sourceMappingURL=types.d.ts.map
`,
);
});
});
2 changes: 2 additions & 0 deletions packages/transformers/typescript-types/src/TSModuleGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ export class TSModuleGraph {
modules: Map<string, TSModule>;
mainModuleName: string;
mainModule: ?TSModule;
syntheticImportCount: number;

constructor(mainModuleName: string) {
this.modules = new Map();
this.mainModuleName = mainModuleName;
this.mainModule = null;
this.syntheticImportCount = 0;
}

addModule(name: string, module: TSModule) {
Expand Down
23 changes: 21 additions & 2 deletions packages/transformers/typescript-types/src/collect.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ export function collect(
}
}

node = ts.visitEachChild(node, visit, context);

if (
ts.isImportTypeNode(node) &&
ts.isLiteralTypeNode(node.argument) &&
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);
}

// Handle `export default name;`
if (ts.isExportAssignment(node) && ts.isIdentifier(node.expression)) {
currentModule.addExport('default', node.expression.text);
Expand Down Expand Up @@ -112,13 +132,12 @@ export function collect(
}
}

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

return ts.visitNode(sourceFile, visit);
Expand Down
24 changes: 24 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2641,6 +2641,25 @@
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109"
integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==

"@types/prop-types@*":
version "15.7.11"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==

"@types/react@^17":
version "17.0.76"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.76.tgz#bfdf762046699e265655cd8f67a51beab6cd1e80"
integrity sha512-w9Aq+qeszGYoQM0hgFcdsAODGJdogadBDiitPm+zjBFJ0mLymvn2qSXsDaLJUndFRqqXk1FQfa9avHUBk1JhJQ==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"

"@types/scheduler@*":
version "0.16.8"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==

"@types/semver@^7.3.12":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
Expand Down Expand Up @@ -5037,6 +5056,11 @@ csstype@^2.6.8:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.11.tgz#452f4d024149ecf260a852b025e36562a253ffc5"
integrity sha512-l8YyEC9NBkSm783PFTvh0FmJy7s5pFKrDp49ZL7zBGX3fWkO+N4EEyan1qqp8cwPLDcD0OSdyY6hAMoxp34JFw==

csstype@^3.0.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==

csstype@^3.0.6:
version "3.1.2"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
Expand Down

0 comments on commit aeaba41

Please sign in to comment.