diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index b053000f15b3f..3d13fe08fbe60 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -2244,7 +2244,7 @@ namespace ts { return node; } - export function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined, isTypeOnly = false) { + export function updateImportClause(node: ImportClause, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined, isTypeOnly: boolean) { return node.name !== name || node.namedBindings !== namedBindings || node.isTypeOnly !== isTypeOnly @@ -2323,7 +2323,7 @@ namespace ts { modifiers: readonly Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined, - isTypeOnly = false) { + isTypeOnly: boolean) { return node.decorators !== decorators || node.modifiers !== modifiers || node.isTypeOnly !== isTypeOnly diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 7746ad00b430e..a84ee54001641 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -686,7 +686,8 @@ namespace ts { return visibleDefaultBinding && updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause( decl.importClause, visibleDefaultBinding, - /*namedBindings*/ undefined + /*namedBindings*/ undefined, + decl.importClause.isTypeOnly, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier)); } if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { @@ -695,7 +696,8 @@ namespace ts { return visibleDefaultBinding || namedBindings ? updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause( decl.importClause, visibleDefaultBinding, - namedBindings + namedBindings, + decl.importClause.isTypeOnly, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined; } // Named imports (optionally with visible default) @@ -708,7 +710,8 @@ namespace ts { updateImportClause( decl.importClause, visibleDefaultBinding, - bindingList && bindingList.length ? updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined + bindingList && bindingList.length ? updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined, + decl.importClause.isTypeOnly, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier) ); @@ -1018,7 +1021,13 @@ namespace ts { resultHasScopeMarker = true; // Always visible if the parent node isn't dropped for being not visible // Rewrite external module names if necessary - return updateExportDeclaration(input, /*decorators*/ undefined, input.modifiers, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier)); + return updateExportDeclaration( + input, + /*decorators*/ undefined, + input.modifiers, + input.exportClause, + rewriteModuleSpecifier(input, input.moduleSpecifier), + input.isTypeOnly); } case SyntaxKind.ExportAssignment: { // Always visible if the parent node isn't dropped for being not visible diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 1d683423a3eb7..f29c792fb3d02 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2781,10 +2781,13 @@ namespace ts { * @param node The import clause node. */ function visitImportClause(node: ImportClause): VisitResult { + if (node.isTypeOnly) { + return undefined; + } // Elide the import clause if we elide both its name and its named bindings. const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings); - return (name || namedBindings) ? updateImportClause(node, name, namedBindings) : undefined; + return (name || namedBindings) ? updateImportClause(node, name, namedBindings, /*isTypeOnly*/ false) : undefined; } /** @@ -2856,7 +2859,8 @@ namespace ts { /*decorators*/ undefined, /*modifiers*/ undefined, exportClause, - node.moduleSpecifier) + node.moduleSpecifier, + node.isTypeOnly) : undefined; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 4f36ccb1b900f..8f8f6fc7b38e9 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -791,7 +791,8 @@ namespace ts { case SyntaxKind.ImportClause: return updateImportClause(node, visitNode((node).name, visitor, isIdentifier), - visitNode((node).namedBindings, visitor, isNamedImportBindings)); + visitNode((node).namedBindings, visitor, isNamedImportBindings), + (node as ImportClause).isTypeOnly); case SyntaxKind.NamespaceImport: return updateNamespaceImport(node, @@ -817,7 +818,8 @@ namespace ts { nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), visitNode((node).exportClause, visitor, isNamedExports), - visitNode((node).moduleSpecifier, visitor, isExpression)); + visitNode((node).moduleSpecifier, visitor, isExpression), + (node as ExportDeclaration).isTypeOnly); case SyntaxKind.NamedExports: return updateNamedExports(node, diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 6db5c9eeadc8c..c7436e88f1372 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -318,7 +318,8 @@ namespace ts.OrganizeImports { exportDecl.decorators, exportDecl.modifiers, updateNamedExports(exportDecl.exportClause!, sortedExportSpecifiers), - exportDecl.moduleSpecifier)); + exportDecl.moduleSpecifier, + exportDecl.isTypeOnly)); return coalescedExports; @@ -358,7 +359,7 @@ namespace ts.OrganizeImports { importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, - updateImportClause(importDeclaration.importClause!, name, namedBindings), // TODO: GH#18217 + updateImportClause(importDeclaration.importClause!, name, namedBindings, importDeclaration.importClause!.isTypeOnly), // TODO: GH#18217 importDeclaration.moduleSpecifier); } diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index b187a0f953b59..a575d86fc4793 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -353,7 +353,7 @@ namespace ts.refactor { changes.replaceNode( sourceFile, importDecl.importClause, - updateImportClause(importDecl.importClause, name, /*namedBindings*/ undefined) + updateImportClause(importDecl.importClause, name, /*namedBindings*/ undefined, importDecl.importClause.isTypeOnly) ); } else if (namedBindings.kind === SyntaxKind.NamedImports) { diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index bcb0c93d1a8c6..89beed673740d 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -220,7 +220,7 @@ namespace ts { const exports = [{ name: "x" }]; const exportSpecifiers = exports.map(e => createExportSpecifier(e.name, e.name)); const exportClause = createNamedExports(exportSpecifiers); - const newEd = updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier); + const newEd = updateExportDeclaration(ed, ed.decorators, ed.modifiers, exportClause, ed.moduleSpecifier, ed.isTypeOnly); return newEd as Node as T; }