diff --git a/tsc/internal/transformers/tstransforms/typeeraser.go b/tsc/internal/transformers/tstransforms/typeeraser.go index 0951065f645a4..0cf768b9d894a 100644 --- a/tsc/internal/transformers/tstransforms/typeeraser.go +++ b/tsc/internal/transformers/tstransforms/typeeraser.go @@ -316,6 +316,13 @@ func (tx *TypeEraserTransformer) visit(node *ast.Node) *ast.Node { } name := n.Name() namedBindings := tx.Visitor().VisitNode(n.NamedBindings) + // Empty {} due to type-only import erasure can be skipped if there is also a default import + if name != nil && namedBindings != nil && ast.IsNamedImports(namedBindings) && + len(namedBindings.AsNamedImports().Elements.Nodes) == 0 && + len(n.NamedBindings.AsNamedImports().Elements.Nodes) != 0 { + // the default binding keeps the import; a source-written {} is left as is + namedBindings = nil + } if name == nil && namedBindings == nil { // all import bindings were elided return nil diff --git a/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.js b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.js new file mode 100644 index 0000000000000..0c74b3089b094 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.js @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts] //// + +//// [a.ts] +export default class A {} +export type T = number; +export const v = 0; + +//// [b.ts] +import A1, { type T } from "./a"; +import A2, { type T as T2, v } from "./a"; +import { type T as T3 } from "./a"; +import A4, {} from "./a"; +import A5, { /* comment */ type T as T5 } from "./a"; +import A6, { + type T as T6, +} from "./a"; + +export { A1, A2, A4, A5, A6, v }; + + +//// [a.js] +export default class A { +} +export const v = 0; +//// [b.js] +import A1 from "./a"; +import A2, { v } from "./a"; +import {} from "./a"; +import A4, {} from "./a"; +import A5 from "./a"; +import A6 from "./a"; +export { A1, A2, A4, A5, A6, v }; diff --git a/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.symbols b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.symbols new file mode 100644 index 0000000000000..69ba53c154567 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.symbols @@ -0,0 +1,52 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts] //// + +=== /a.ts === +export default class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export type T = number; +>T : Symbol(T, Decl(a.ts, 0, 25)) + +export const v = 0; +>v : Symbol(v, Decl(a.ts, 2, 12)) + +=== /b.ts === +import A1, { type T } from "./a"; +>A1 : Symbol(A1, Decl(b.ts, 0, 6)) +>T : Symbol(T, Decl(b.ts, 0, 12)) + +import A2, { type T as T2, v } from "./a"; +>A2 : Symbol(A2, Decl(b.ts, 1, 6)) +>T : Symbol(T, Decl(a.ts, 0, 25)) +>T2 : Symbol(T2, Decl(b.ts, 1, 12)) +>v : Symbol(v, Decl(b.ts, 1, 26)) + +import { type T as T3 } from "./a"; +>T : Symbol(T, Decl(a.ts, 0, 25)) +>T3 : Symbol(T3, Decl(b.ts, 2, 8)) + +import A4, {} from "./a"; +>A4 : Symbol(A4, Decl(b.ts, 3, 6)) + +import A5, { /* comment */ type T as T5 } from "./a"; +>A5 : Symbol(A5, Decl(b.ts, 4, 6)) +>T : Symbol(T, Decl(a.ts, 0, 25)) +>T5 : Symbol(T5, Decl(b.ts, 4, 12)) + +import A6, { +>A6 : Symbol(A6, Decl(b.ts, 5, 6)) + + type T as T6, +>T : Symbol(T, Decl(a.ts, 0, 25)) +>T6 : Symbol(T6, Decl(b.ts, 5, 12)) + +} from "./a"; + +export { A1, A2, A4, A5, A6, v }; +>A1 : Symbol(A1, Decl(b.ts, 9, 8)) +>A2 : Symbol(A2, Decl(b.ts, 9, 12)) +>A4 : Symbol(A4, Decl(b.ts, 9, 16)) +>A5 : Symbol(A5, Decl(b.ts, 9, 20)) +>A6 : Symbol(A6, Decl(b.ts, 9, 24)) +>v : Symbol(v, Decl(b.ts, 9, 28)) + diff --git a/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.types b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.types new file mode 100644 index 0000000000000..c1a21faad0abb --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.types @@ -0,0 +1,53 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts] //// + +=== /a.ts === +export default class A {} +>A : A + +export type T = number; +>T : number + +export const v = 0; +>v : 0 +>0 : 0 + +=== /b.ts === +import A1, { type T } from "./a"; +>A1 : typeof A1 +>T : any + +import A2, { type T as T2, v } from "./a"; +>A2 : typeof A1 +>T : any +>T2 : any +>v : 0 + +import { type T as T3 } from "./a"; +>T : any +>T3 : any + +import A4, {} from "./a"; +>A4 : typeof A1 + +import A5, { /* comment */ type T as T5 } from "./a"; +>A5 : typeof A1 +>T : any +>T5 : any + +import A6, { +>A6 : typeof A1 + + type T as T6, +>T : any +>T6 : any + +} from "./a"; + +export { A1, A2, A4, A5, A6, v }; +>A1 : typeof A1 +>A2 : typeof A1 +>A4 : typeof A1 +>A5 : typeof A1 +>A6 : typeof A1 +>v : 0 + diff --git a/tsc/testdata/tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts b/tsc/testdata/tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts new file mode 100644 index 0000000000000..6cbcb27edb62a --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/verbatimModuleSyntaxDefaultImportTypeOnlyNamed.ts @@ -0,0 +1,21 @@ +// @target: esnext +// @module: esnext +// @moduleResolution: bundler +// @verbatimModuleSyntax: true + +// @Filename: /a.ts +export default class A {} +export type T = number; +export const v = 0; + +// @Filename: /b.ts +import A1, { type T } from "./a"; +import A2, { type T as T2, v } from "./a"; +import { type T as T3 } from "./a"; +import A4, {} from "./a"; +import A5, { /* comment */ type T as T5 } from "./a"; +import A6, { + type T as T6, +} from "./a"; + +export { A1, A2, A4, A5, A6, v };