From e76cb26a5235acab34bde8e30d76a4f618451fb8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 5 Nov 2025 16:13:57 -0800 Subject: [PATCH 1/2] Remove getNameFromImportDeclaration in favor of Node.Name() --- internal/checker/checker.go | 2 +- internal/checker/utilities.go | 14 -------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 38fb708983..d131109923 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -13987,7 +13987,7 @@ func (c *Checker) checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(nod // TODO: how to get name for export *? name := "*" if !ast.IsExportDeclaration(typeOnlyDeclaration) { - name = getNameFromImportDeclaration(typeOnlyDeclaration).Text() + name = typeOnlyDeclaration.Name().Text() } c.error(decl.ModuleReference, message).AddRelatedInfo(createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)) } diff --git a/internal/checker/utilities.go b/internal/checker/utilities.go index bd026c259c..3271fe0aeb 100644 --- a/internal/checker/utilities.go +++ b/internal/checker/utilities.go @@ -189,20 +189,6 @@ func IsInTypeQuery(node *ast.Node) bool { }) != nil } -func getNameFromImportDeclaration(node *ast.Node) *ast.Node { - switch node.Kind { - case ast.KindImportSpecifier: - return node.AsImportSpecifier().Name() - case ast.KindNamespaceImport: - return node.AsNamespaceImport().Name() - case ast.KindImportClause: - return node.AsImportClause().Name() - case ast.KindImportEqualsDeclaration: - return node.AsImportEqualsDeclaration().Name() - } - return nil -} - func nodeCanBeDecorated(useLegacyDecorators bool, node *ast.Node, parent *ast.Node, grandparent *ast.Node) bool { // private names cannot be used with decorators yet if useLegacyDecorators && node.Name() != nil && ast.IsPrivateIdentifier(node.Name()) { From 8fce6ed5c6a2ab47a401f817ca4a3215dc0e5274 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 5 Nov 2025 16:14:07 -0800 Subject: [PATCH 2/2] Add regression test --- .../importAliasTypeOnlyExport.errors.txt | 14 ++++++++++++++ .../importAliasTypeOnlyExport.symbols | 19 +++++++++++++++++++ .../compiler/importAliasTypeOnlyExport.types | 19 +++++++++++++++++++ .../compiler/importAliasTypeOnlyExport.ts | 11 +++++++++++ 4 files changed, 63 insertions(+) create mode 100644 testdata/baselines/reference/compiler/importAliasTypeOnlyExport.errors.txt create mode 100644 testdata/baselines/reference/compiler/importAliasTypeOnlyExport.symbols create mode 100644 testdata/baselines/reference/compiler/importAliasTypeOnlyExport.types create mode 100644 testdata/tests/cases/compiler/importAliasTypeOnlyExport.ts diff --git a/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.errors.txt b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.errors.txt new file mode 100644 index 0000000000..39c8d40771 --- /dev/null +++ b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.errors.txt @@ -0,0 +1,14 @@ +t.ts(2,14): error TS1379: An import alias cannot reference a declaration that was exported using 'export type'. + + +==== t.ts (1 errors) ==== + import a = require("./a"); + import foo = a.Foo + ~~~~~ +!!! error TS1379: An import alias cannot reference a declaration that was exported using 'export type'. +!!! related TS1377 a.ts:2:15: 'Foo' was exported here. + +==== a.ts (0 errors) ==== + type Foo = { x: number } + export type { Foo }; + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.symbols b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.symbols new file mode 100644 index 0000000000..fa41228c5e --- /dev/null +++ b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.symbols @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/importAliasTypeOnlyExport.ts] //// + +=== t.ts === +import a = require("./a"); +>a : Symbol(a, Decl(t.ts, 0, 0)) + +import foo = a.Foo +>foo : Symbol(foo, Decl(t.ts, 0, 26)) +>a : Symbol(a, Decl(t.ts, 0, 0)) +>Foo : Symbol(a.Foo, Decl(a.ts, 1, 13)) + +=== a.ts === +type Foo = { x: number } +>Foo : Symbol(Foo, Decl(a.ts, 0, 0)) +>x : Symbol(x, Decl(a.ts, 0, 12)) + +export type { Foo }; +>Foo : Symbol(Foo, Decl(a.ts, 1, 13)) + diff --git a/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.types b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.types new file mode 100644 index 0000000000..73e51f003e --- /dev/null +++ b/testdata/baselines/reference/compiler/importAliasTypeOnlyExport.types @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/importAliasTypeOnlyExport.ts] //// + +=== t.ts === +import a = require("./a"); +>a : typeof a + +import foo = a.Foo +>foo : any +>a : typeof a +>Foo : foo + +=== a.ts === +type Foo = { x: number } +>Foo : Foo +>x : number + +export type { Foo }; +>Foo : Foo + diff --git a/testdata/tests/cases/compiler/importAliasTypeOnlyExport.ts b/testdata/tests/cases/compiler/importAliasTypeOnlyExport.ts new file mode 100644 index 0000000000..032fdc3eb0 --- /dev/null +++ b/testdata/tests/cases/compiler/importAliasTypeOnlyExport.ts @@ -0,0 +1,11 @@ +// @target: esnext +// @module: commonjs +// @noEmit: true + +// @filename: t.ts +import a = require("./a"); +import foo = a.Foo + +// @filename: a.ts +type Foo = { x: number } +export type { Foo };