diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index cc3da23d2067b..1777974761563 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2301,7 +2301,10 @@ export function transformTypeScript(context: TransformationContext): Transformer } else { // Elide named imports if all of its import specifiers are elided and settings allow. - const allowEmpty = compilerOptions.verbatimModuleSyntax; + // When a default import exists, avoid keeping empty named braces under verbatimModuleSyntax. + const parentImportClause = node.parent as ImportClause | undefined; + const defaultBindingPresent = !!parentImportClause?.name; + const allowEmpty = compilerOptions.verbatimModuleSyntax && !defaultBindingPresent; const elements = visitNodes(node.elements, visitImportSpecifier, isImportSpecifier); return allowEmpty || some(elements) ? factory.updateNamedImports(node, elements) : undefined; } diff --git a/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.js b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.js new file mode 100644 index 0000000000000..4c6a5331226da --- /dev/null +++ b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.js @@ -0,0 +1,58 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts] //// + +//// [verbatimModuleSyntaxEmptyNamedImport_module.ts] +export const ValueExport = 0; +export type TypeOnlyExport = number; +const DefaultExport = class {}; +export default DefaultExport; + +//// [verbatimModuleSyntaxEmptyNamedImport_module.d.ts] +declare module "verbatimModuleSyntaxEmptyNamedImport_module"; + +//// [verbatimModuleSyntaxEmptyNamedImport_test.ts] +import DefaultExportA, { + type TypeOnlyExport as TypeOnlyExportA, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportB, { + type TypeOnlyExport as TypeOnlyExportB, + ValueExport as ValueExportB, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportC, { + ValueExport as RenamedValueExportC, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportD from "verbatimModuleSyntaxEmptyNamedImport_module"; +import { type TypeOnlyExport as RenamedTypeOnlyExportE } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import { ValueExport as RenamedValueExportF } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import * as NamespaceImportG from "verbatimModuleSyntaxEmptyNamedImport_module"; + +new DefaultExportA(); +new DefaultExportB(); +new DefaultExportC(); +new DefaultExportD(); +console.log(ValueExportB); +console.log(RenamedValueExportC); +console.log(RenamedValueExportF); +console.log(NamespaceImportG.ValueExport); + + +//// [verbatimModuleSyntaxEmptyNamedImport_module.js] +export const ValueExport = 0; +const DefaultExport = class { +}; +export default DefaultExport; +//// [verbatimModuleSyntaxEmptyNamedImport_test.js] +import DefaultExportA from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportB, { ValueExport as ValueExportB, } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportC, { ValueExport as RenamedValueExportC, } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportD from "verbatimModuleSyntaxEmptyNamedImport_module"; +import {} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import { ValueExport as RenamedValueExportF } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import * as NamespaceImportG from "verbatimModuleSyntaxEmptyNamedImport_module"; +new DefaultExportA(); +new DefaultExportB(); +new DefaultExportC(); +new DefaultExportD(); +console.log(ValueExportB); +console.log(RenamedValueExportC); +console.log(RenamedValueExportF); +console.log(NamespaceImportG.ValueExport); diff --git a/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.symbols b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.symbols new file mode 100644 index 0000000000000..dc14d6ab8616e --- /dev/null +++ b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.symbols @@ -0,0 +1,98 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts] //// + +=== verbatimModuleSyntaxEmptyNamedImport_module.ts === +export const ValueExport = 0; +>ValueExport : Symbol(ValueExport, Decl(verbatimModuleSyntaxEmptyNamedImport_module.ts, 0, 12)) + +export type TypeOnlyExport = number; +>TypeOnlyExport : Symbol(TypeOnlyExport, Decl(verbatimModuleSyntaxEmptyNamedImport_module.ts, 0, 29)) + +const DefaultExport = class {}; +>DefaultExport : Symbol(DefaultExport, Decl(verbatimModuleSyntaxEmptyNamedImport_module.ts, 2, 5)) + +export default DefaultExport; +>DefaultExport : Symbol(DefaultExport, Decl(verbatimModuleSyntaxEmptyNamedImport_module.ts, 2, 5)) + +=== verbatimModuleSyntaxEmptyNamedImport_module.d.ts === +declare module "verbatimModuleSyntaxEmptyNamedImport_module"; +>"verbatimModuleSyntaxEmptyNamedImport_module" : Symbol("verbatimModuleSyntaxEmptyNamedImport_module", Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) + +=== verbatimModuleSyntaxEmptyNamedImport_test.ts === +import DefaultExportA, { +>DefaultExportA : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 0, 6)) + + type TypeOnlyExport as TypeOnlyExportA, +>TypeOnlyExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>TypeOnlyExportA : Symbol(TypeOnlyExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 0, 24)) + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportB, { +>DefaultExportB : Symbol(DefaultExportB, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 3, 6)) + + type TypeOnlyExport as TypeOnlyExportB, +>TypeOnlyExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>TypeOnlyExportB : Symbol(TypeOnlyExportB, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 3, 24)) + + ValueExport as ValueExportB, +>ValueExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>ValueExportB : Symbol(ValueExportB, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 4, 41)) + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportC, { +>DefaultExportC : Symbol(DefaultExportC, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 7, 6)) + + ValueExport as RenamedValueExportC, +>ValueExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>RenamedValueExportC : Symbol(RenamedValueExportC, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 7, 24)) + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportD from "verbatimModuleSyntaxEmptyNamedImport_module"; +>DefaultExportD : Symbol(DefaultExportD, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 10, 6)) + +import { type TypeOnlyExport as RenamedTypeOnlyExportE } from "verbatimModuleSyntaxEmptyNamedImport_module"; +>TypeOnlyExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>RenamedTypeOnlyExportE : Symbol(RenamedTypeOnlyExportE, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 11, 8)) + +import { ValueExport as RenamedValueExportF } from "verbatimModuleSyntaxEmptyNamedImport_module"; +>ValueExport : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_module.d.ts, 0, 0)) +>RenamedValueExportF : Symbol(RenamedValueExportF, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 12, 8)) + +import * as NamespaceImportG from "verbatimModuleSyntaxEmptyNamedImport_module"; +>NamespaceImportG : Symbol(NamespaceImportG, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 13, 6)) + +new DefaultExportA(); +>DefaultExportA : Symbol(DefaultExportA, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 0, 6)) + +new DefaultExportB(); +>DefaultExportB : Symbol(DefaultExportB, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 3, 6)) + +new DefaultExportC(); +>DefaultExportC : Symbol(DefaultExportC, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 7, 6)) + +new DefaultExportD(); +>DefaultExportD : Symbol(DefaultExportD, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 10, 6)) + +console.log(ValueExportB); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>ValueExportB : Symbol(ValueExportB, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 4, 41)) + +console.log(RenamedValueExportC); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>RenamedValueExportC : Symbol(RenamedValueExportC, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 7, 24)) + +console.log(RenamedValueExportF); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>RenamedValueExportF : Symbol(RenamedValueExportF, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 12, 8)) + +console.log(NamespaceImportG.ValueExport); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>NamespaceImportG : Symbol(NamespaceImportG, Decl(verbatimModuleSyntaxEmptyNamedImport_test.ts, 13, 6)) + diff --git a/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.types b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.types new file mode 100644 index 0000000000000..e9060bcac72e4 --- /dev/null +++ b/tests/baselines/reference/verbatimModuleSyntaxEmptyNamedImport.types @@ -0,0 +1,150 @@ +//// [tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts] //// + +=== verbatimModuleSyntaxEmptyNamedImport_module.ts === +export const ValueExport = 0; +>ValueExport : 0 +> : ^ +>0 : 0 +> : ^ + +export type TypeOnlyExport = number; +>TypeOnlyExport : number +> : ^^^^^^ + +const DefaultExport = class {}; +>DefaultExport : typeof DefaultExport +> : ^^^^^^^^^^^^^^^^^^^^ +>class {} : typeof DefaultExport +> : ^^^^^^^^^^^^^^^^^^^^ + +export default DefaultExport; +>DefaultExport : typeof DefaultExport +> : ^^^^^^^^^^^^^^^^^^^^ + +=== verbatimModuleSyntaxEmptyNamedImport_module.d.ts === +declare module "verbatimModuleSyntaxEmptyNamedImport_module"; +>"verbatimModuleSyntaxEmptyNamedImport_module" : any + +=== verbatimModuleSyntaxEmptyNamedImport_test.ts === +import DefaultExportA, { +>DefaultExportA : any +> : ^^^ + + type TypeOnlyExport as TypeOnlyExportA, +>TypeOnlyExport : any +> : ^^^ +>TypeOnlyExportA : any +> : ^^^ + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportB, { +>DefaultExportB : any +> : ^^^ + + type TypeOnlyExport as TypeOnlyExportB, +>TypeOnlyExport : any +> : ^^^ +>TypeOnlyExportB : any +> : ^^^ + + ValueExport as ValueExportB, +>ValueExport : any +> : ^^^ +>ValueExportB : any +> : ^^^ + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportC, { +>DefaultExportC : any +> : ^^^ + + ValueExport as RenamedValueExportC, +>ValueExport : any +> : ^^^ +>RenamedValueExportC : any +> : ^^^ + +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportD from "verbatimModuleSyntaxEmptyNamedImport_module"; +>DefaultExportD : any +> : ^^^ + +import { type TypeOnlyExport as RenamedTypeOnlyExportE } from "verbatimModuleSyntaxEmptyNamedImport_module"; +>TypeOnlyExport : any +> : ^^^ +>RenamedTypeOnlyExportE : any +> : ^^^ + +import { ValueExport as RenamedValueExportF } from "verbatimModuleSyntaxEmptyNamedImport_module"; +>ValueExport : any +> : ^^^ +>RenamedValueExportF : any +> : ^^^ + +import * as NamespaceImportG from "verbatimModuleSyntaxEmptyNamedImport_module"; +>NamespaceImportG : any + +new DefaultExportA(); +>new DefaultExportA() : any +>DefaultExportA : any + +new DefaultExportB(); +>new DefaultExportB() : any +>DefaultExportB : any + +new DefaultExportC(); +>new DefaultExportC() : any +>DefaultExportC : any + +new DefaultExportD(); +>new DefaultExportD() : any +>DefaultExportD : any + +console.log(ValueExportB); +>console.log(ValueExportB) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>ValueExportB : any + +console.log(RenamedValueExportC); +>console.log(RenamedValueExportC) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>RenamedValueExportC : any + +console.log(RenamedValueExportF); +>console.log(RenamedValueExportF) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>RenamedValueExportF : any + +console.log(NamespaceImportG.ValueExport); +>console.log(NamespaceImportG.ValueExport) : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>NamespaceImportG.ValueExport : any +>NamespaceImportG : any +> : ^^^ +>ValueExport : any +> : ^^^ + diff --git a/tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts b/tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts new file mode 100644 index 0000000000000..72eb79966f02e --- /dev/null +++ b/tests/cases/compiler/verbatimModuleSyntaxEmptyNamedImport.ts @@ -0,0 +1,37 @@ +// @target: esnext +// @module: preserve +// @verbatimModuleSyntax: true + +// @filename: verbatimModuleSyntaxEmptyNamedImport_module.ts +export const ValueExport = 0; +export type TypeOnlyExport = number; +const DefaultExport = class {}; +export default DefaultExport; + +// @filename: verbatimModuleSyntaxEmptyNamedImport_module.d.ts +declare module "verbatimModuleSyntaxEmptyNamedImport_module"; + +// @filename: verbatimModuleSyntaxEmptyNamedImport_test.ts +import DefaultExportA, { + type TypeOnlyExport as TypeOnlyExportA, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportB, { + type TypeOnlyExport as TypeOnlyExportB, + ValueExport as ValueExportB, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportC, { + ValueExport as RenamedValueExportC, +} from "verbatimModuleSyntaxEmptyNamedImport_module"; +import DefaultExportD from "verbatimModuleSyntaxEmptyNamedImport_module"; +import { type TypeOnlyExport as RenamedTypeOnlyExportE } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import { ValueExport as RenamedValueExportF } from "verbatimModuleSyntaxEmptyNamedImport_module"; +import * as NamespaceImportG from "verbatimModuleSyntaxEmptyNamedImport_module"; + +new DefaultExportA(); +new DefaultExportB(); +new DefaultExportC(); +new DefaultExportD(); +console.log(ValueExportB); +console.log(RenamedValueExportC); +console.log(RenamedValueExportF); +console.log(NamespaceImportG.ValueExport);