From 2f6c6dd97de631f6c11b2fc26fd453913811f495 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 23 Oct 2025 14:46:26 -0700 Subject: [PATCH 1/2] Access exportTypeLinks instead of valueSymbolLinks --- internal/checker/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 7c943729dd..8c68eafb19 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -9755,7 +9755,7 @@ func (c *Checker) invocationErrorRecovery(apparentType *Type, kind SignatureKind // Create a diagnostic on the originating import if possible onto which we can attach a quickfix // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site if importNode != nil && !ast.IsImportCall(importNode) { - sigs := c.getSignaturesOfType(c.getTypeOfSymbol(c.valueSymbolLinks.Get(apparentType.symbol).target), kind) + sigs := c.getSignaturesOfType(c.getTypeOfSymbol(c.exportTypeLinks.Get(apparentType.symbol).target), kind) if len(sigs) == 0 { return } From ddab966c5e7c55b19d68df2ab6bbe1fffec2c1ef Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 23 Oct 2025 14:46:41 -0700 Subject: [PATCH 2/2] Add regression test --- .../invocationErrorRecovery.errors.txt | 16 ++++++++++++++++ .../compiler/invocationErrorRecovery.symbols | 19 +++++++++++++++++++ .../compiler/invocationErrorRecovery.types | 18 ++++++++++++++++++ .../cases/compiler/invocationErrorRecovery.ts | 11 +++++++++++ 4 files changed, 64 insertions(+) create mode 100644 testdata/baselines/reference/compiler/invocationErrorRecovery.errors.txt create mode 100644 testdata/baselines/reference/compiler/invocationErrorRecovery.symbols create mode 100644 testdata/baselines/reference/compiler/invocationErrorRecovery.types create mode 100644 testdata/tests/cases/compiler/invocationErrorRecovery.ts diff --git a/testdata/baselines/reference/compiler/invocationErrorRecovery.errors.txt b/testdata/baselines/reference/compiler/invocationErrorRecovery.errors.txt new file mode 100644 index 0000000000..aaabcef494 --- /dev/null +++ b/testdata/baselines/reference/compiler/invocationErrorRecovery.errors.txt @@ -0,0 +1,16 @@ +index.ts(2,1): error TS2349: This expression is not callable. + Type '{ default: () => void; }' has no call signatures. + + +==== foo.d.ts (0 errors) ==== + declare function foo(): void; + declare namespace foo {} + export = foo; +==== index.ts (1 errors) ==== + import * as foo from "./foo"; + foo() + ~~~ +!!! error TS2349: This expression is not callable. +!!! error TS2349: Type '{ default: () => void; }' has no call signatures. +!!! related TS7038 index.ts:1:1: Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/invocationErrorRecovery.symbols b/testdata/baselines/reference/compiler/invocationErrorRecovery.symbols new file mode 100644 index 0000000000..4dfa6b4fd9 --- /dev/null +++ b/testdata/baselines/reference/compiler/invocationErrorRecovery.symbols @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/invocationErrorRecovery.ts] //// + +=== foo.d.ts === +declare function foo(): void; +>foo : Symbol(foo, Decl(foo.d.ts, 0, 0), Decl(foo.d.ts, 0, 29)) + +declare namespace foo {} +>foo : Symbol(foo, Decl(foo.d.ts, 0, 0), Decl(foo.d.ts, 0, 29)) + +export = foo; +>foo : Symbol(foo, Decl(foo.d.ts, 0, 0), Decl(foo.d.ts, 0, 29)) + +=== index.ts === +import * as foo from "./foo"; +>foo : Symbol(foo, Decl(index.ts, 0, 6)) + +foo() +>foo : Symbol(foo, Decl(index.ts, 0, 6)) + diff --git a/testdata/baselines/reference/compiler/invocationErrorRecovery.types b/testdata/baselines/reference/compiler/invocationErrorRecovery.types new file mode 100644 index 0000000000..5bdbe9b0e7 --- /dev/null +++ b/testdata/baselines/reference/compiler/invocationErrorRecovery.types @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/invocationErrorRecovery.ts] //// + +=== foo.d.ts === +declare function foo(): void; +>foo : () => void + +declare namespace foo {} +export = foo; +>foo : () => void + +=== index.ts === +import * as foo from "./foo"; +>foo : { default: () => void; } + +foo() +>foo() : any +>foo : { default: () => void; } + diff --git a/testdata/tests/cases/compiler/invocationErrorRecovery.ts b/testdata/tests/cases/compiler/invocationErrorRecovery.ts new file mode 100644 index 0000000000..5b0387fe96 --- /dev/null +++ b/testdata/tests/cases/compiler/invocationErrorRecovery.ts @@ -0,0 +1,11 @@ +// @module: nodenext +// @target: esnext +// @strict: true +// @noEmit: true +// @filename: foo.d.ts +declare function foo(): void; +declare namespace foo {} +export = foo; +// @filename: index.ts +import * as foo from "./foo"; +foo()