Skip to content

Commit 66edca1

Browse files
Fix: Consult referenced project options for synthetic default export eligibility (#63038)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: andrewbranch <[email protected]> Co-authored-by: Andrew Branch <[email protected]>
1 parent 1143279 commit 66edca1

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
37943794
// are ESM, there cannot be a synthetic default.
37953795
return false;
37963796
}
3797+
// For other files (not node16/nodenext with impliedNodeFormat), check if we can determine
3798+
// the module format from project references
3799+
if (!targetMode && file.isDeclarationFile) {
3800+
// Try to get the project reference - try both source file mapping and output file mapping
3801+
// since declaration files can be mapped either way depending on how they're resolved
3802+
const redirect = host.getRedirectFromSourceFile(file.path) || host.getRedirectFromOutput(file.path);
3803+
if (redirect) {
3804+
// This is a declaration file from a project reference, so we can determine
3805+
// its module format from the referenced project's options
3806+
const targetModuleKind = host.getEmitModuleFormatOfFile(file);
3807+
if (usageMode === ModuleKind.ESNext && ModuleKind.ES2015 <= targetModuleKind && targetModuleKind <= ModuleKind.ESNext) {
3808+
return false;
3809+
}
3810+
}
3811+
}
37973812
}
37983813
if (!allowSyntheticDefaultImports) {
37993814
return false;

src/testRunner/unittests/tsc/projectReferences.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,42 @@ describe("unittests:: tsc:: projectReferences::", () => {
9090
commandLineArgs: ["--p", "app", "--pretty", "false"],
9191
});
9292

93+
verifyTsc({
94+
scenario: "projectReferences",
95+
subScenario: "referenced project with esnext module disallows synthetic default imports",
96+
sys: () =>
97+
TestServerHost.createWatchedSystem({
98+
"/home/src/workspaces/project/lib/tsconfig.json": jsonToReadableText({
99+
compilerOptions: {
100+
composite: true,
101+
declaration: true,
102+
module: "esnext",
103+
moduleResolution: "bundler",
104+
rootDir: "src",
105+
outDir: "dist",
106+
},
107+
include: ["src"],
108+
}),
109+
"/home/src/workspaces/project/lib/src/utils.ts": "export const test = () => 'test';",
110+
"/home/src/workspaces/project/lib/dist/utils.d.ts": "export declare const test: () => string;",
111+
"/home/src/workspaces/project/app/tsconfig.json": jsonToReadableText({
112+
compilerOptions: {
113+
module: "esnext",
114+
moduleResolution: "bundler",
115+
},
116+
references: [
117+
{ path: "../lib" },
118+
],
119+
}),
120+
"/home/src/workspaces/project/app/index.ts": `
121+
import TestSrc from '../lib/src/utils'; // Error
122+
import TestDecl from '../lib/dist/utils'; // Error
123+
console.log(TestSrc.test());
124+
console.log(TestDecl.test());`,
125+
}),
126+
commandLineArgs: ["--p", "app", "--pretty", "false"],
127+
});
128+
93129
verifyTsc({
94130
scenario: "projectReferences",
95131
subScenario: "referencing ambient const enum from referenced project with preserveConstEnums",

tests/baselines/reference/tsc/projectReferences/default-import-interop-uses-referenced-project-settings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ declare const console: { log(msg: any): void; };
8686
Output::
8787
app/src/index.ts(2,28): error TS2613: Module '"/home/src/workspaces/project/app/src/local"' has no default export. Did you mean to use 'import { local } from "/home/src/workspaces/project/app/src/local"' instead?
8888
app/src/index.ts(3,28): error TS2613: Module '"/home/src/workspaces/project/node_modules/esm-package/index"' has no default export. Did you mean to use 'import { esm } from "/home/src/workspaces/project/node_modules/esm-package/index"' instead?
89+
app/src/index.ts(4,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/a"' has no default export.
90+
app/src/index.ts(5,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/a"' has no default export.
8991

9092

9193
//// [/home/src/workspaces/project/app/dist/local.js]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
currentDirectory:: /home/src/workspaces/project useCaseSensitiveFileNames:: false
2+
Input::
3+
//// [/home/src/workspaces/project/lib/tsconfig.json]
4+
{
5+
"compilerOptions": {
6+
"composite": true,
7+
"declaration": true,
8+
"module": "esnext",
9+
"moduleResolution": "bundler",
10+
"rootDir": "src",
11+
"outDir": "dist"
12+
},
13+
"include": [
14+
"src"
15+
]
16+
}
17+
18+
//// [/home/src/workspaces/project/lib/src/utils.ts]
19+
export const test = () => 'test';
20+
21+
//// [/home/src/workspaces/project/lib/dist/utils.d.ts]
22+
export declare const test: () => string;
23+
24+
//// [/home/src/workspaces/project/app/tsconfig.json]
25+
{
26+
"compilerOptions": {
27+
"module": "esnext",
28+
"moduleResolution": "bundler"
29+
},
30+
"references": [
31+
{
32+
"path": "../lib"
33+
}
34+
]
35+
}
36+
37+
//// [/home/src/workspaces/project/app/index.ts]
38+
39+
import TestSrc from '../lib/src/utils'; // Error
40+
import TestDecl from '../lib/dist/utils'; // Error
41+
console.log(TestSrc.test());
42+
console.log(TestDecl.test());
43+
44+
//// [/home/src/tslibs/TS/Lib/lib.d.ts]
45+
interface Boolean {}
46+
interface Function {}
47+
interface CallableFunction {}
48+
interface NewableFunction {}
49+
interface IArguments {}
50+
interface Number { toExponential: any; }
51+
interface Object {}
52+
interface RegExp {}
53+
interface String { charAt: any; }
54+
interface Array<T> { length: number; [n: number]: T; }
55+
interface ReadonlyArray<T> {}
56+
declare const console: { log(msg: any): void; };
57+
58+
59+
/home/src/tslibs/TS/Lib/tsc.js --p app --pretty false
60+
Output::
61+
app/index.ts(2,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/utils"' has no default export.
62+
app/index.ts(3,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/utils"' has no default export.
63+
64+
65+
//// [/home/src/workspaces/project/app/index.js]
66+
import TestSrc from '../lib/src/utils'; // Error
67+
import TestDecl from '../lib/dist/utils'; // Error
68+
console.log(TestSrc.test());
69+
console.log(TestDecl.test());
70+
71+
72+
73+
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated

0 commit comments

Comments
 (0)