From f352f1c23f867a3cae8174d3640ff3566ed2f7bd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:06:19 +0000 Subject: [PATCH 1/3] Initial plan From 7f69f3ca5e378c2452df56900de8e159b6ace3a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 00:43:52 +0000 Subject: [PATCH 2/3] Fix: Respect allowSyntheticDefaultImports for export specifiers When re-exporting with `export { default as Foo } from "./b"`, the compiler should respect the `allowSyntheticDefaultImports` option even for TypeScript source files (not just declaration files). The fix adds logic in `getTargetofModuleDefault` to allow synthetic defaults for export specifiers when `allowSyntheticDefaultImports` is enabled. This is consistent with the intent of the option to allow treating modules without a default export as if they had one. Fixes tests: - reexportMissingDefault.ts - reexportMissingDefault1.ts - reexportMissingDefault2.ts - reexportMissingDefault3.ts Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com> --- src/compiler/checker.ts | 9 ++++++++- .../reference/reexportMissingDefault.errors.txt | 11 ----------- .../baselines/reference/reexportMissingDefault.types | 5 ++--- .../reference/reexportMissingDefault1.errors.txt | 12 ------------ .../reference/reexportMissingDefault1.types | 5 ++--- .../reference/reexportMissingDefault2.errors.txt | 11 ----------- .../reference/reexportMissingDefault2.types | 5 ++--- .../reference/reexportMissingDefault3.errors.txt | 11 ----------- .../reference/reexportMissingDefault3.symbols | 1 + .../reference/reexportMissingDefault3.types | 9 ++++----- 10 files changed, 19 insertions(+), 60 deletions(-) delete mode 100644 tests/baselines/reference/reexportMissingDefault.errors.txt delete mode 100644 tests/baselines/reference/reexportMissingDefault1.errors.txt delete mode 100644 tests/baselines/reference/reexportMissingDefault2.errors.txt delete mode 100644 tests/baselines/reference/reexportMissingDefault3.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fa2a56e2fdfa6..85be34b8d2925 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3869,7 +3869,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return exportDefaultSymbol; } const hasDefaultOnly = isOnlyImportableAsDefault(specifier, moduleSymbol); - const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); + let hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); + // For export specifiers re-exporting 'default', when allowSyntheticDefaultImports is enabled, + // allow synthetic default even from TypeScript source files (not just declaration files). + // This is consistent with the intent of allowSyntheticDefaultImports to allow treating modules + // without a default export as if they had one. + if (!hasSyntheticDefault && isExportSpecifier(node) && allowSyntheticDefaultImports) { + hasSyntheticDefault = true; + } if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol) && !allowSyntheticDefaultImports) { const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; diff --git a/tests/baselines/reference/reexportMissingDefault.errors.txt b/tests/baselines/reference/reexportMissingDefault.errors.txt deleted file mode 100644 index 91637fa1f741f..0000000000000 --- a/tests/baselines/reference/reexportMissingDefault.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. - - -==== b.ts (0 errors) ==== - export const b = null; - -==== a.ts (1 errors) ==== - export { b } from "./b"; - export { default } from "./b"; - ~~~~~~~ -!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault.types b/tests/baselines/reference/reexportMissingDefault.types index afba6a1c2f77f..3ef3ab2eeef4b 100644 --- a/tests/baselines/reference/reexportMissingDefault.types +++ b/tests/baselines/reference/reexportMissingDefault.types @@ -3,7 +3,6 @@ === b.ts === export const b = null; >b : any -> : ^^^ === a.ts === export { b } from "./b"; @@ -11,6 +10,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : any -> : ^^^ +>default : typeof import("b") +> : ^^^^^^^^^^^^^^^^^^ diff --git a/tests/baselines/reference/reexportMissingDefault1.errors.txt b/tests/baselines/reference/reexportMissingDefault1.errors.txt deleted file mode 100644 index dfee891aa421c..0000000000000 --- a/tests/baselines/reference/reexportMissingDefault1.errors.txt +++ /dev/null @@ -1,12 +0,0 @@ -a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. - - -==== b.ts (0 errors) ==== - export const b = null; - -==== a.ts (1 errors) ==== - export { b } from "./b"; - export { default } from "./b"; - ~~~~~~~ -!!! error TS2305: Module '"./b"' has no exported member 'default'. - \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault1.types b/tests/baselines/reference/reexportMissingDefault1.types index 3b058c8337bc7..7527bc6cad3e3 100644 --- a/tests/baselines/reference/reexportMissingDefault1.types +++ b/tests/baselines/reference/reexportMissingDefault1.types @@ -3,7 +3,6 @@ === b.ts === export const b = null; >b : any -> : ^^^ === a.ts === export { b } from "./b"; @@ -11,6 +10,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : any -> : ^^^ +>default : typeof import("b") +> : ^^^^^^^^^^^^^^^^^^ diff --git a/tests/baselines/reference/reexportMissingDefault2.errors.txt b/tests/baselines/reference/reexportMissingDefault2.errors.txt deleted file mode 100644 index 91637fa1f741f..0000000000000 --- a/tests/baselines/reference/reexportMissingDefault2.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. - - -==== b.ts (0 errors) ==== - export const b = null; - -==== a.ts (1 errors) ==== - export { b } from "./b"; - export { default } from "./b"; - ~~~~~~~ -!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault2.types b/tests/baselines/reference/reexportMissingDefault2.types index 56de966eefd02..f003a83ba9671 100644 --- a/tests/baselines/reference/reexportMissingDefault2.types +++ b/tests/baselines/reference/reexportMissingDefault2.types @@ -3,7 +3,6 @@ === b.ts === export const b = null; >b : any -> : ^^^ === a.ts === export { b } from "./b"; @@ -11,6 +10,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : any -> : ^^^ +>default : typeof import("b") +> : ^^^^^^^^^^^^^^^^^^ diff --git a/tests/baselines/reference/reexportMissingDefault3.errors.txt b/tests/baselines/reference/reexportMissingDefault3.errors.txt deleted file mode 100644 index b7965fa1eb3b6..0000000000000 --- a/tests/baselines/reference/reexportMissingDefault3.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. - - -==== b.ts (0 errors) ==== - export const b = null; - -==== a.ts (1 errors) ==== - export { b } from "./b"; - export { default as a } from "./b"; - ~~~~~~~ -!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault3.symbols b/tests/baselines/reference/reexportMissingDefault3.symbols index 4c505a73a309d..2c6fdef6f2dcc 100644 --- a/tests/baselines/reference/reexportMissingDefault3.symbols +++ b/tests/baselines/reference/reexportMissingDefault3.symbols @@ -9,5 +9,6 @@ export { b } from "./b"; >b : Symbol(b, Decl(a.ts, 0, 8)) export { default as a } from "./b"; +>default : Symbol("b", Decl(b.ts, 0, 0)) >a : Symbol(a, Decl(a.ts, 1, 8)) diff --git a/tests/baselines/reference/reexportMissingDefault3.types b/tests/baselines/reference/reexportMissingDefault3.types index b6908bed4be81..6ad7f16080a59 100644 --- a/tests/baselines/reference/reexportMissingDefault3.types +++ b/tests/baselines/reference/reexportMissingDefault3.types @@ -3,7 +3,6 @@ === b.ts === export const b = null; >b : any -> : ^^^ === a.ts === export { b } from "./b"; @@ -11,8 +10,8 @@ export { b } from "./b"; > : ^^^ export { default as a } from "./b"; ->default : any -> : ^^^ ->a : any -> : ^^^ +>default : typeof import("b") +> : ^^^^^^^^^^^^^^^^^^ +>a : typeof import("b") +> : ^^^^^^^^^^^^^^^^^^ From d85f072dddc5b55388ed6ddc0bebd89f2a9e72e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:06:49 +0000 Subject: [PATCH 3/3] Fix: Only allow synthetic defaults for declaration files in export specifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrected the fix to only allow synthetic defaults when re-exporting from declaration files (not TypeScript source files). This aligns with the issue description which states that declaration files may correspond to CommonJS modules at runtime where a default import can reference the whole module.exports symbol. Only tests targeting .d.ts files should pass without errors: - reexportMissingDefault4.ts (targets b.d.ts) ✓ - reexportMissingDefault5.ts (targets b.d.ts) ✓ Tests targeting .ts files correctly maintain their errors: - reexportMissingDefault.ts, 1, 2, 3, 6, 7 (all target b.ts) Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com> --- src/compiler/checker.ts | 9 ++++----- .../reference/reexportMissingDefault.errors.txt | 11 +++++++++++ .../baselines/reference/reexportMissingDefault.types | 5 +++-- .../reference/reexportMissingDefault1.errors.txt | 12 ++++++++++++ .../reference/reexportMissingDefault1.types | 5 +++-- .../reference/reexportMissingDefault2.errors.txt | 11 +++++++++++ .../reference/reexportMissingDefault2.types | 5 +++-- .../reference/reexportMissingDefault3.errors.txt | 11 +++++++++++ .../reference/reexportMissingDefault3.symbols | 1 - .../reference/reexportMissingDefault3.types | 9 +++++---- 10 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/reexportMissingDefault.errors.txt create mode 100644 tests/baselines/reference/reexportMissingDefault1.errors.txt create mode 100644 tests/baselines/reference/reexportMissingDefault2.errors.txt create mode 100644 tests/baselines/reference/reexportMissingDefault3.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 85be34b8d2925..8f420077f27ac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3870,11 +3870,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const hasDefaultOnly = isOnlyImportableAsDefault(specifier, moduleSymbol); let hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); - // For export specifiers re-exporting 'default', when allowSyntheticDefaultImports is enabled, - // allow synthetic default even from TypeScript source files (not just declaration files). - // This is consistent with the intent of allowSyntheticDefaultImports to allow treating modules - // without a default export as if they had one. - if (!hasSyntheticDefault && isExportSpecifier(node) && allowSyntheticDefaultImports) { + // For export specifiers re-exporting 'default' from declaration files, when allowSyntheticDefaultImports + // is enabled, allow synthetic default. Declaration files may correspond to CommonJS modules at runtime, + // where a default import is allowed to reference the whole module.exports symbol. + if (!hasSyntheticDefault && isExportSpecifier(node) && allowSyntheticDefaultImports && (!file || file.isDeclarationFile)) { hasSyntheticDefault = true; } if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { diff --git a/tests/baselines/reference/reexportMissingDefault.errors.txt b/tests/baselines/reference/reexportMissingDefault.errors.txt new file mode 100644 index 0000000000000..91637fa1f741f --- /dev/null +++ b/tests/baselines/reference/reexportMissingDefault.errors.txt @@ -0,0 +1,11 @@ +a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. + + +==== b.ts (0 errors) ==== + export const b = null; + +==== a.ts (1 errors) ==== + export { b } from "./b"; + export { default } from "./b"; + ~~~~~~~ +!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault.types b/tests/baselines/reference/reexportMissingDefault.types index 3ef3ab2eeef4b..afba6a1c2f77f 100644 --- a/tests/baselines/reference/reexportMissingDefault.types +++ b/tests/baselines/reference/reexportMissingDefault.types @@ -3,6 +3,7 @@ === b.ts === export const b = null; >b : any +> : ^^^ === a.ts === export { b } from "./b"; @@ -10,6 +11,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : typeof import("b") -> : ^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ diff --git a/tests/baselines/reference/reexportMissingDefault1.errors.txt b/tests/baselines/reference/reexportMissingDefault1.errors.txt new file mode 100644 index 0000000000000..dfee891aa421c --- /dev/null +++ b/tests/baselines/reference/reexportMissingDefault1.errors.txt @@ -0,0 +1,12 @@ +a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. + + +==== b.ts (0 errors) ==== + export const b = null; + +==== a.ts (1 errors) ==== + export { b } from "./b"; + export { default } from "./b"; + ~~~~~~~ +!!! error TS2305: Module '"./b"' has no exported member 'default'. + \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault1.types b/tests/baselines/reference/reexportMissingDefault1.types index 7527bc6cad3e3..3b058c8337bc7 100644 --- a/tests/baselines/reference/reexportMissingDefault1.types +++ b/tests/baselines/reference/reexportMissingDefault1.types @@ -3,6 +3,7 @@ === b.ts === export const b = null; >b : any +> : ^^^ === a.ts === export { b } from "./b"; @@ -10,6 +11,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : typeof import("b") -> : ^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ diff --git a/tests/baselines/reference/reexportMissingDefault2.errors.txt b/tests/baselines/reference/reexportMissingDefault2.errors.txt new file mode 100644 index 0000000000000..91637fa1f741f --- /dev/null +++ b/tests/baselines/reference/reexportMissingDefault2.errors.txt @@ -0,0 +1,11 @@ +a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. + + +==== b.ts (0 errors) ==== + export const b = null; + +==== a.ts (1 errors) ==== + export { b } from "./b"; + export { default } from "./b"; + ~~~~~~~ +!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault2.types b/tests/baselines/reference/reexportMissingDefault2.types index f003a83ba9671..56de966eefd02 100644 --- a/tests/baselines/reference/reexportMissingDefault2.types +++ b/tests/baselines/reference/reexportMissingDefault2.types @@ -3,6 +3,7 @@ === b.ts === export const b = null; >b : any +> : ^^^ === a.ts === export { b } from "./b"; @@ -10,6 +11,6 @@ export { b } from "./b"; > : ^^^ export { default } from "./b"; ->default : typeof import("b") -> : ^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ diff --git a/tests/baselines/reference/reexportMissingDefault3.errors.txt b/tests/baselines/reference/reexportMissingDefault3.errors.txt new file mode 100644 index 0000000000000..b7965fa1eb3b6 --- /dev/null +++ b/tests/baselines/reference/reexportMissingDefault3.errors.txt @@ -0,0 +1,11 @@ +a.ts(2,10): error TS2305: Module '"./b"' has no exported member 'default'. + + +==== b.ts (0 errors) ==== + export const b = null; + +==== a.ts (1 errors) ==== + export { b } from "./b"; + export { default as a } from "./b"; + ~~~~~~~ +!!! error TS2305: Module '"./b"' has no exported member 'default'. \ No newline at end of file diff --git a/tests/baselines/reference/reexportMissingDefault3.symbols b/tests/baselines/reference/reexportMissingDefault3.symbols index 2c6fdef6f2dcc..4c505a73a309d 100644 --- a/tests/baselines/reference/reexportMissingDefault3.symbols +++ b/tests/baselines/reference/reexportMissingDefault3.symbols @@ -9,6 +9,5 @@ export { b } from "./b"; >b : Symbol(b, Decl(a.ts, 0, 8)) export { default as a } from "./b"; ->default : Symbol("b", Decl(b.ts, 0, 0)) >a : Symbol(a, Decl(a.ts, 1, 8)) diff --git a/tests/baselines/reference/reexportMissingDefault3.types b/tests/baselines/reference/reexportMissingDefault3.types index 6ad7f16080a59..b6908bed4be81 100644 --- a/tests/baselines/reference/reexportMissingDefault3.types +++ b/tests/baselines/reference/reexportMissingDefault3.types @@ -3,6 +3,7 @@ === b.ts === export const b = null; >b : any +> : ^^^ === a.ts === export { b } from "./b"; @@ -10,8 +11,8 @@ export { b } from "./b"; > : ^^^ export { default as a } from "./b"; ->default : typeof import("b") -> : ^^^^^^^^^^^^^^^^^^ ->a : typeof import("b") -> : ^^^^^^^^^^^^^^^^^^ +>default : any +> : ^^^ +>a : any +> : ^^^