Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3812,6 +3812,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// it definitely is a module and does not have a synthetic default
return false;
}
// If this is a declaration file from a project reference, check the referenced project's options
// to determine if the module format is ESM
if (file) {
const redirect = host.getRedirectFromSourceFile(file.path);
if (redirect?.resolvedRef) {
const referencedOptions = redirect.resolvedRef.commandLine.options;
// If the referenced project has allowSyntheticDefaultImports disabled, respect that
if (!getAllowSyntheticDefaultImports(referencedOptions)) {
return false;
}
// If the referenced project's module format is ESM (ES2015 or later),
// it cannot have a synthetic default
const referencedModuleKind = referencedOptions.module ?? ModuleKind.CommonJS;
if (referencedModuleKind >= ModuleKind.ES2015) {
return false;
}
}
}
// There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set
// Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member
// as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm
Expand Down
29 changes: 29 additions & 0 deletions src/testRunner/unittests/tsc/projectReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,35 @@ describe("unittests:: tsc:: projectReferences::", () => {
commandLineArgs: ["--p", "app", "--pretty", "false"],
});

verifyTsc({
scenario: "projectReferences",
subScenario: "referenced project with esnext module disallows synthetic default imports",
sys: () =>
TestServerHost.createWatchedSystem({
"/home/src/workspaces/project/lib/tsconfig.json": jsonToReadableText({
compilerOptions: {
composite: true,
declaration: true,
module: "esnext",
moduleResolution: "bundler",
},
}),
"/home/src/workspaces/project/lib/utils.ts": "export const test = () => 'test';",
"/home/src/workspaces/project/lib/utils.d.ts": "export declare const test: () => string;",
"/home/src/workspaces/project/app/tsconfig.json": jsonToReadableText({
compilerOptions: {
module: "esnext",
moduleResolution: "bundler",
},
references: [
{ path: "../lib" },
],
}),
"/home/src/workspaces/project/app/index.ts": `import Test from '../lib/utils';\nconsole.log(Test.test());`,
}),
commandLineArgs: ["--p", "app", "--pretty", "false"],
});

verifyTsc({
scenario: "projectReferences",
subScenario: "referencing ambient const enum from referenced project with preserveConstEnums",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ declare const console: { log(msg: any): void; };
Output::
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?
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?
app/src/index.ts(4,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/a"' has no default export.
app/src/index.ts(5,28): error TS1192: Module '"/home/src/workspaces/project/lib/dist/a"' has no default export.
Comment on lines +89 to +90
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The presence of these errors was actually always asserted in the test content (lines 66–67 in the baseline). Not sure if this used to work and regressed without noticing or what, but this baseline change matches the original intention.



//// [/home/src/workspaces/project/app/dist/local.js]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
currentDirectory:: /home/src/workspaces/project useCaseSensitiveFileNames:: false
Input::
//// [/home/src/workspaces/project/lib/tsconfig.json]
{
"compilerOptions": {
"composite": true,
"declaration": true,
"module": "esnext",
"moduleResolution": "bundler"
}
}

//// [/home/src/workspaces/project/lib/utils.ts]
export const test = () => 'test';

//// [/home/src/workspaces/project/lib/utils.d.ts]
export declare const test: () => string;

//// [/home/src/workspaces/project/app/tsconfig.json]
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler"
},
"references": [
{
"path": "../lib"
}
]
}

//// [/home/src/workspaces/project/app/index.ts]
import Test from '../lib/utils';
console.log(Test.test());

//// [/home/src/tslibs/TS/Lib/lib.d.ts]
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };


/home/src/tslibs/TS/Lib/tsc.js --p app --pretty false
Output::
app/index.ts(1,8): error TS1192: Module '"/home/src/workspaces/project/lib/utils"' has no default export.


//// [/home/src/workspaces/project/app/index.js]
import Test from '../lib/utils';
console.log(Test.test());



exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
Loading