diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d1241098c..ea35af4c80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2482,7 +2482,7 @@ namespace ts { const immediate = resolveExternalModuleName( node, getExternalModuleRequireArgument(node) || getExternalModuleImportEqualsDeclarationExpression(node)); - const resolved = resolveExternalModuleSymbol(immediate); + const resolved = resolveExternalModuleSymbol(immediate); markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false); return resolved; } @@ -2492,7 +2492,7 @@ namespace ts { } function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) { - if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false)) { + if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfNode(node))!; const isExport = typeOnlyDeclarationIsExport(typeOnlyDeclaration); const message = isExport @@ -6841,6 +6841,7 @@ namespace ts { addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + /*isTypeOnly*/ false, uniqueName, factory.createExternalModuleReference(factory.createStringLiteral(specifier)) ), ModifierFlags.None); @@ -6848,6 +6849,7 @@ namespace ts { addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + /*isTypeOnly*/ false, factory.createIdentifier(localName), factory.createQualifiedName(uniqueName, initializer.name as Identifier), ), modifierFlags); @@ -6867,6 +6869,7 @@ namespace ts { addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + /*isTypeOnly*/ false, factory.createIdentifier(localName), isLocalImport ? symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) @@ -7024,6 +7027,7 @@ namespace ts { addResult(factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + /*isTypeOnly*/ false, factory.createIdentifier(varName), symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) ), ModifierFlags.None); @@ -36459,9 +36463,12 @@ namespace ts { checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); } } + if (node.isTypeOnly) { + grammarErrorOnNode(node, Diagnostics.An_import_alias_cannot_use_import_type); + } } else { - if (moduleKind >= ModuleKind.ES2015 && !(node.flags & NodeFlags.Ambient)) { + if (moduleKind >= ModuleKind.ES2015 && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) { // Import equals declaration is deprecated in es6 or above grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } @@ -36552,19 +36559,30 @@ namespace ts { }); } + function canConvertImportDeclarationToTypeOnly(statement: Statement) { + return isImportDeclaration(statement) && + statement.importClause && + !statement.importClause.isTypeOnly && + importClauseContainsReferencedImport(statement.importClause) && + !isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) && + !importClauseContainsConstEnumUsedAsValue(statement.importClause); + } + + function canConvertImportEqualsDeclarationToTypeOnly(statement: Statement) { + return isImportEqualsDeclaration(statement) && + isExternalModuleReference(statement.moduleReference) && + !statement.isTypeOnly && + getSymbolOfNode(statement).isReferenced && + !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) && + !getSymbolLinks(getSymbolOfNode(statement)).constEnumReferenced; + } + function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) { for (const statement of sourceFile.statements) { - if ( - isImportDeclaration(statement) && - statement.importClause && - !statement.importClause.isTypeOnly && - importClauseContainsReferencedImport(statement.importClause) && - !isReferencedAliasDeclaration(statement.importClause, /*checkChildren*/ true) && - !importClauseContainsConstEnumUsedAsValue(statement.importClause) - ) { + if (canConvertImportDeclarationToTypeOnly(statement) || canConvertImportEqualsDeclarationToTypeOnly(statement)) { error( statement, - Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_the_importsNotUsedAsValues_is_set_to_error); + Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error); } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4cb607631f..cabacfaa01 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1112,11 +1112,7 @@ "category": "Message", "code": 1369 }, - "Only ECMAScript imports may use 'import type'.": { - "category": "Error", - "code": 1370 - }, - "This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'.": { + "This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'.": { "category": "Error", "code": 1371 }, @@ -1196,6 +1192,10 @@ "category": "Error", "code": 1391 }, + "An import alias cannot use 'import type'": { + "category": "Error", + "code": 1392 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 83a0a7ed9d..7f77f70880 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3155,6 +3155,10 @@ namespace ts { emitModifiers(node, node.modifiers); emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); + if (node.isTypeOnly) { + emitTokenWithComment(SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); + writeSpace(); + } emit(node.name); writeSpace(); emitTokenWithComment(SyntaxKind.EqualsToken, node.name.end, writePunctuation, node); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index aadd082a46..176c9154dc 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -3776,6 +3776,7 @@ namespace ts { function createImportEqualsDeclaration( decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, + isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference ) { @@ -3785,6 +3786,7 @@ namespace ts { modifiers, name ); + node.isTypeOnly = isTypeOnly; node.moduleReference = moduleReference; node.transformFlags |= propagateChildFlags(node.moduleReference); if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript; @@ -3797,14 +3799,16 @@ namespace ts { node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, + isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference ) { return node.decorators !== decorators || node.modifiers !== modifiers + || node.isTypeOnly !== isTypeOnly || node.name !== name || node.moduleReference !== moduleReference - ? update(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) + ? update(createImportEqualsDeclaration(decorators, modifiers, isTypeOnly, name, moduleReference), node) : node; } @@ -5798,7 +5802,7 @@ namespace ts { isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.type) : isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifiers, node.name, node.members) : isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifiers, node.name, node.body) : - isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifiers, node.name, node.moduleReference) : + isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.name, node.moduleReference) : isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifiers, node.importClause, node.moduleSpecifier) : isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifiers, node.expression) : isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier) : diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ac810e305a..5dcfb5ee07 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6929,11 +6929,8 @@ namespace ts { parseExpected(SyntaxKind.EqualsToken); const moduleReference = parseModuleReference(); parseSemicolon(); - const node = factory.createImportEqualsDeclaration(decorators, modifiers, identifier, moduleReference); + const node = factory.createImportEqualsDeclaration(decorators, modifiers, isTypeOnly, identifier, moduleReference); const finished = withJSDoc(finishNode(node, pos), hasJSDoc); - if (isTypeOnly) { - parseErrorAtRange(finished, Diagnostics.Only_ECMAScript_imports_may_use_import_type); - } return finished; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index ccb9dae665..1fc500d2da 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -681,6 +681,7 @@ namespace ts { decl, /*decorators*/ undefined, decl.modifiers, + decl.isTypeOnly, decl.name, factory.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier)) ); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 98fff3625a..9cc9c1c3fc 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2973,6 +2973,11 @@ namespace ts { * @param node The import equals declaration node. */ function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult { + // Always elide type-only imports + if (node.isTypeOnly) { + return undefined; + } + if (isExternalModuleImportEqualsDeclaration(node)) { const isReferenced = resolver.isReferencedAliasDeclaration(node); // If the alias is unreferenced but we want to keep the import, replace with 'import "mod"'. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7c9038ed3b..34245a5e40 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2925,6 +2925,7 @@ namespace ts { readonly kind: SyntaxKind.ImportEqualsDeclaration; readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; + readonly isTypeOnly: boolean; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external // module reference. @@ -3037,6 +3038,7 @@ namespace ts { export type TypeOnlyCompatibleAliasDeclaration = | ImportClause + | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier ; @@ -7001,8 +7003,8 @@ namespace ts { updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 0f702eba48..6722e7ad5b 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1107,7 +1107,8 @@ namespace ts { case SyntaxKind.NamespaceImport: return (node as NamespaceImport).parent.isTypeOnly; case SyntaxKind.ImportClause: - return (node as ImportClause).isTypeOnly; + case SyntaxKind.ImportEqualsDeclaration: + return (node as ImportClause | ImportEqualsDeclaration).isTypeOnly; default: return false; } diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index 8a06e11055..ad6e45f401 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -937,6 +937,7 @@ namespace ts { return factory.updateImportEqualsDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), + (node).isTypeOnly, nodeVisitor((node).name, visitor, isIdentifier), nodeVisitor((node).moduleReference, visitor, isModuleReference)); @@ -949,7 +950,7 @@ namespace ts { case SyntaxKind.ImportClause: return factory.updateImportClause(node, - (node as ImportClause).isTypeOnly, + (node).isTypeOnly, nodeVisitor((node).name, visitor, isIdentifier), nodeVisitor((node).namedBindings, visitor, isNamedImportBindings)); @@ -980,7 +981,7 @@ namespace ts { return factory.updateExportDeclaration(node, nodesVisitor((node).decorators, visitor, isDecorator), nodesVisitor((node).modifiers, visitor, isModifier), - (node as ExportDeclaration).isTypeOnly, + (node).isTypeOnly, nodeVisitor((node).exportClause, visitor, isNamedExportBindings), nodeVisitor((node).moduleSpecifier, visitor, isExpression)); diff --git a/src/services/codefixes/convertToTypeOnlyImport.ts b/src/services/codefixes/convertToTypeOnlyImport.ts index 7079ee8d2b..daa163250d 100644 --- a/src/services/codefixes/convertToTypeOnlyImport.ts +++ b/src/services/codefixes/convertToTypeOnlyImport.ts @@ -1,6 +1,6 @@ /* @internal */ namespace ts.codefix { - const errorCodes = [Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_the_importsNotUsedAsValues_is_set_to_error.code]; + const errorCodes = [Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error.code]; const fixId = "convertToTypeOnlyImport"; registerCodeFix({ errorCodes, diff --git a/src/services/codefixes/fixInvalidImportSyntax.ts b/src/services/codefixes/fixInvalidImportSyntax.ts index acc033df36..9728cc032f 100644 --- a/src/services/codefixes/fixInvalidImportSyntax.ts +++ b/src/services/codefixes/fixInvalidImportSyntax.ts @@ -16,6 +16,7 @@ namespace ts.codefix { variations.push(createAction(context, sourceFile, node, factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + /*isTypeOnly*/ false, namespace.name, factory.createExternalModuleReference(node.moduleSpecifier) ))); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 407903390e..4ba390cca9 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -795,6 +795,7 @@ namespace ts.codefix { ? factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, + typeOnly, factory.createIdentifier(namespaceLikeImport.name), factory.createExternalModuleReference(quotedModuleSpecifier)) : factory.createImportDeclaration( diff --git a/src/services/codefixes/requireInTs.ts b/src/services/codefixes/requireInTs.ts index f990f5cadb..c1ee73013f 100644 --- a/src/services/codefixes/requireInTs.ts +++ b/src/services/codefixes/requireInTs.ts @@ -24,7 +24,7 @@ namespace ts.codefix { function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, info: Info) { const { allowSyntheticDefaults, defaultImportName, namedImports, statement, required } = info; changes.replaceNode(sourceFile, statement, defaultImportName && !allowSyntheticDefaults - ? factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, defaultImportName, factory.createExternalModuleReference(required)) + ? factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, defaultImportName, factory.createExternalModuleReference(required)) : factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, namedImports), required)); } diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index 8c3f450492..bf5609620e 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -245,7 +245,7 @@ namespace ts.refactor { factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamespaceImport(newNamespaceId)), newModuleString); case SyntaxKind.ImportEqualsDeclaration: - return factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, newNamespaceId, factory.createExternalModuleReference(newModuleString)); + return factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, newNamespaceId, factory.createExternalModuleReference(newModuleString)); case SyntaxKind.VariableDeclaration: return factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); default: @@ -782,7 +782,7 @@ namespace ts.refactor { case SyntaxKind.InterfaceDeclaration: return factory.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); case SyntaxKind.ImportEqualsDeclaration: - return factory.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.name, d.moduleReference); + return factory.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.isTypeOnly, d.name, d.moduleReference); case SyntaxKind.ExpressionStatement: return Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c269e0f0b0..ccc5d1fa1f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1598,6 +1598,7 @@ declare namespace ts { readonly kind: SyntaxKind.ImportEqualsDeclaration; readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; + readonly isTypeOnly: boolean; readonly moduleReference: ModuleReference; } export interface ExternalModuleReference extends Node { @@ -1668,7 +1669,7 @@ declare namespace ts { readonly name: Identifier; } export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - export type TypeOnlyCompatibleAliasDeclaration = ImportClause | NamespaceImport | ImportOrExportSpecifier; + export type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -3410,8 +3411,8 @@ declare namespace ts { updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; @@ -10505,9 +10506,9 @@ declare namespace ts { /** @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. */ const updateNamespaceExportDeclaration: (node: NamespaceExportDeclaration, name: Identifier) => NamespaceExportDeclaration; /** @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ - const createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; + const createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; /** @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ - const updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; + const updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; /** @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. */ const createImportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration; /** @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index f985d34fdd..440cebf6b0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1598,6 +1598,7 @@ declare namespace ts { readonly kind: SyntaxKind.ImportEqualsDeclaration; readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; + readonly isTypeOnly: boolean; readonly moduleReference: ModuleReference; } export interface ExternalModuleReference extends Node { @@ -1668,7 +1669,7 @@ declare namespace ts { readonly name: Identifier; } export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - export type TypeOnlyCompatibleAliasDeclaration = ImportClause | NamespaceImport | ImportOrExportSpecifier; + export type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -3410,8 +3411,8 @@ declare namespace ts { updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]): CaseBlock; createNamespaceExportDeclaration(name: string | Identifier): NamespaceExportDeclaration; updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier): NamespaceExportDeclaration; - createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; - updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + createImportEqualsDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; + updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference): ImportEqualsDeclaration; createImportDeclaration(decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression): ImportDeclaration; createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause; @@ -6865,9 +6866,9 @@ declare namespace ts { /** @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. */ const updateNamespaceExportDeclaration: (node: NamespaceExportDeclaration, name: Identifier) => NamespaceExportDeclaration; /** @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ - const createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; + const createImportEqualsDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: string | Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; /** @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ - const updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; + const updateImportEqualsDeclaration: (node: ImportEqualsDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, name: Identifier, moduleReference: ModuleReference) => ImportEqualsDeclaration; /** @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. */ const createImportDeclaration: (decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression) => ImportDeclaration; /** @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. */ diff --git a/tests/baselines/reference/cjsImportInES2015.js b/tests/baselines/reference/cjsImportInES2015.js new file mode 100644 index 0000000000..25daeab406 --- /dev/null +++ b/tests/baselines/reference/cjsImportInES2015.js @@ -0,0 +1,14 @@ +//// [tests/cases/conformance/externalModules/typeOnly/cjsImportInES2015.ts] //// + +//// [index.d.ts] +declare class SpecialError extends Error {} +export = SpecialError; + +//// [index.ts] +import type SpecialError = require("cjs-dep"); +function handleError(err: SpecialError) {} + + +//// [index.js] +function handleError(err) { } +export {}; diff --git a/tests/baselines/reference/cjsImportInES2015.symbols b/tests/baselines/reference/cjsImportInES2015.symbols new file mode 100644 index 0000000000..8620d585bb --- /dev/null +++ b/tests/baselines/reference/cjsImportInES2015.symbols @@ -0,0 +1,17 @@ +=== /project/index.ts === +import type SpecialError = require("cjs-dep"); +>SpecialError : Symbol(SpecialError, Decl(index.ts, 0, 0)) + +function handleError(err: SpecialError) {} +>handleError : Symbol(handleError, Decl(index.ts, 0, 46)) +>err : Symbol(err, Decl(index.ts, 1, 21)) +>SpecialError : Symbol(SpecialError, Decl(index.ts, 0, 0)) + +=== /project/node_modules/cjs-dep/index.d.ts === +declare class SpecialError extends Error {} +>SpecialError : Symbol(SpecialError, Decl(index.d.ts, 0, 0)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +export = SpecialError; +>SpecialError : Symbol(SpecialError, Decl(index.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/cjsImportInES2015.types b/tests/baselines/reference/cjsImportInES2015.types new file mode 100644 index 0000000000..e4a5a81465 --- /dev/null +++ b/tests/baselines/reference/cjsImportInES2015.types @@ -0,0 +1,16 @@ +=== /project/index.ts === +import type SpecialError = require("cjs-dep"); +>SpecialError : typeof SpecialError + +function handleError(err: SpecialError) {} +>handleError : (err: SpecialError) => void +>err : SpecialError + +=== /project/node_modules/cjs-dep/index.d.ts === +declare class SpecialError extends Error {} +>SpecialError : SpecialError +>Error : Error + +export = SpecialError; +>SpecialError : SpecialError + diff --git a/tests/baselines/reference/grammarErrors.errors.txt b/tests/baselines/reference/grammarErrors.errors.txt index ad9d7c9f85..bf1009be1c 100644 --- a/tests/baselines/reference/grammarErrors.errors.txt +++ b/tests/baselines/reference/grammarErrors.errors.txt @@ -4,6 +4,7 @@ error TS5056: Cannot write file '/a.js' because it would be overwritten by multi /a.js(1,1): error TS8006: 'import type' declarations can only be used in TypeScript files. /a.js(2,1): error TS8006: 'export type' declarations can only be used in TypeScript files. /b.ts(1,8): error TS1363: A type-only import can specify a default import or named bindings, but not both. +/c.ts(4,1): error TS1392: An import alias cannot use 'import type' !!! error TS5055: Cannot write file '/a.js' because it would overwrite input file. @@ -26,4 +27,12 @@ error TS5056: Cannot write file '/a.js' because it would be overwritten by multi export type { A }; ~~~~~~~~~~~~~~~~~~ !!! error TS8006: 'export type' declarations can only be used in TypeScript files. + +==== /c.ts (1 errors) ==== + namespace ns { + export class Foo {} + } + import type Foo = ns.Foo; + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1392: An import alias cannot use 'import type' \ No newline at end of file diff --git a/tests/baselines/reference/grammarErrors.js b/tests/baselines/reference/grammarErrors.js index bb1e4e1d1e..16acd74514 100644 --- a/tests/baselines/reference/grammarErrors.js +++ b/tests/baselines/reference/grammarErrors.js @@ -12,7 +12,23 @@ import type A, { B, C } from './a'; import type A from './a'; export type { A }; +//// [c.ts] +namespace ns { + export class Foo {} +} +import type Foo = ns.Foo; + //// [b.js] "use strict"; exports.__esModule = true; +//// [c.js] +var ns; +(function (ns) { + var Foo = /** @class */ (function () { + function Foo() { + } + return Foo; + }()); + ns.Foo = Foo; +})(ns || (ns = {})); diff --git a/tests/baselines/reference/importEqualsDeclaration.errors.txt b/tests/baselines/reference/importEqualsDeclaration.errors.txt new file mode 100644 index 0000000000..3e338465de --- /dev/null +++ b/tests/baselines/reference/importEqualsDeclaration.errors.txt @@ -0,0 +1,23 @@ +/c.ts(4,1): error TS1361: 'A' cannot be used as a value because it was imported using 'import type'. + + +==== /c.ts (1 errors) ==== + import type A = require('./a'); // Ok + import type = require('./b'); // Ok + + A.prototype; // Error + ~ +!!! error TS1361: 'A' cannot be used as a value because it was imported using 'import type'. +!!! related TS1376 /c.ts:1:1: 'A' was imported here. + const a: A = { a: 'a' }; // Ok + void type; // Ok + export declare const AConstructor: typeof A; // Ok + +==== /a.ts (0 errors) ==== + class A { a!: string } + export = A; + +==== /b.ts (0 errors) ==== + class SomeClass {} + export = SomeClass; + \ No newline at end of file diff --git a/tests/baselines/reference/importEqualsDeclaration.js b/tests/baselines/reference/importEqualsDeclaration.js new file mode 100644 index 0000000000..56ee60e471 --- /dev/null +++ b/tests/baselines/reference/importEqualsDeclaration.js @@ -0,0 +1,57 @@ +//// [tests/cases/conformance/externalModules/typeOnly/importEqualsDeclaration.ts] //// + +//// [a.ts] +class A { a!: string } +export = A; + +//// [b.ts] +class SomeClass {} +export = SomeClass; + +//// [c.ts] +import type A = require('./a'); // Ok +import type = require('./b'); // Ok + +A.prototype; // Error +const a: A = { a: 'a' }; // Ok +void type; // Ok +export declare const AConstructor: typeof A; // Ok + + +//// [a.js] +"use strict"; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +module.exports = A; +//// [b.js] +"use strict"; +var SomeClass = /** @class */ (function () { + function SomeClass() { + } + return SomeClass; +}()); +module.exports = SomeClass; +//// [c.js] +"use strict"; +exports.__esModule = true; +var type = require("./b"); // Ok +A.prototype; // Error +var a = { a: 'a' }; // Ok +void type; // Ok + + +//// [a.d.ts] +declare class A { + a: string; +} +export = A; +//// [b.d.ts] +declare class SomeClass { +} +export = SomeClass; +//// [c.d.ts] +import type A = require('./a'); +export declare const AConstructor: typeof A; diff --git a/tests/baselines/reference/importEqualsDeclarationError.errors.txt b/tests/baselines/reference/importEqualsDeclarationError.errors.txt deleted file mode 100644 index 1d3f606b3e..0000000000 --- a/tests/baselines/reference/importEqualsDeclarationError.errors.txt +++ /dev/null @@ -1,17 +0,0 @@ -/c.ts(1,1): error TS1370: Only ECMAScript imports may use 'import type'. - - -==== /c.ts (1 errors) ==== - import type T = require('./a'); // Error - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1370: Only ECMAScript imports may use 'import type'. - import type = require('./b'); // Ok - -==== /a.ts (0 errors) ==== - type T = {}; - export = T; - -==== /b.ts (0 errors) ==== - class SomeClass {} - export = SomeClass; - \ No newline at end of file diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt b/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt index 8fd9453361..7bc4014bc5 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt +++ b/tests/baselines/reference/importsNotUsedAsValues_error.errors.txt @@ -1,7 +1,8 @@ -/b.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. -/c.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +/b.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. +/c.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. /e.ts(1,1): error TS6192: All imports in import declaration are unused. -/g.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +/g.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. +/i.ts(1,1): error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. ==== /a.ts (0 errors) ==== @@ -13,7 +14,7 @@ ==== /b.ts (1 errors) ==== import { A, B } from './a'; // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +!!! error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. let a: A; let b: B; console.log(a, b); @@ -21,7 +22,7 @@ ==== /c.ts (1 errors) ==== import Default, * as named from './a'; // Error ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +!!! error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. let a: Default; let b: named.B; console.log(a, b); @@ -48,7 +49,32 @@ ==== /g.ts (1 errors) ==== import { C } from './a'; ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +!!! error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. let c: C; let d: C.Two; - console.log(c, d); \ No newline at end of file + console.log(c, d); + +==== /h.ts (0 errors) ==== + class H {} + export = H; + +==== /i.ts (1 errors) ==== + import H = require('./h'); // Error + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. + let h: H = {}; + console.log(h); + +==== /j.ts (0 errors) ==== + import H = require('./h'); // noUnusedLocals error only + +==== /k.ts (0 errors) ==== + const enum K { One, Two } + export = K; + +==== /l.ts (0 errors) ==== + import K = require('./k'); + K.One; + +==== /j.ts (0 errors) ==== + // Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 \ No newline at end of file diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.js b/tests/baselines/reference/importsNotUsedAsValues_error.js index 19c4362589..e7ccbd7b21 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.js +++ b/tests/baselines/reference/importsNotUsedAsValues_error.js @@ -39,7 +39,30 @@ console.log(c, d); import { C } from './a'; let c: C; let d: C.Two; -console.log(c, d); +console.log(c, d); + +//// [h.ts] +class H {} +export = H; + +//// [i.ts] +import H = require('./h'); // Error +let h: H = {}; +console.log(h); + +//// [j.ts] +import H = require('./h'); // noUnusedLocals error only + +//// [k.ts] +const enum K { One, Two } +export = K; + +//// [l.ts] +import K = require('./k'); +K.One; + +//// [j.ts] +// Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 //// [a.js] "use strict"; @@ -97,3 +120,25 @@ require("./a"); var c; var d; console.log(c, d); +//// [h.js] +"use strict"; +var H = /** @class */ (function () { + function H() { + } + return H; +}()); +module.exports = H; +//// [i.js] +"use strict"; +exports.__esModule = true; +var h = {}; +console.log(h); +//// [j.js] +// Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 +//// [k.js] +"use strict"; +exports.__esModule = true; +//// [l.js] +"use strict"; +exports.__esModule = true; +0 /* One */; diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.symbols b/tests/baselines/reference/importsNotUsedAsValues_error.symbols index bc6b9ec5be..28fcb0ff1d 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.symbols +++ b/tests/baselines/reference/importsNotUsedAsValues_error.symbols @@ -132,3 +132,48 @@ console.log(c, d); >c : Symbol(c, Decl(g.ts, 1, 3)) >d : Symbol(d, Decl(g.ts, 2, 3)) +=== /h.ts === +class H {} +>H : Symbol(H, Decl(h.ts, 0, 0)) + +export = H; +>H : Symbol(H, Decl(h.ts, 0, 0)) + +=== /i.ts === +import H = require('./h'); // Error +>H : Symbol(H, Decl(i.ts, 0, 0)) + +let h: H = {}; +>h : Symbol(h, Decl(i.ts, 1, 3)) +>H : Symbol(H, Decl(i.ts, 0, 0)) + +console.log(h); +>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, --, --)) +>h : Symbol(h, Decl(i.ts, 1, 3)) + +=== /j.ts === +import H = require('./h'); // noUnusedLocals error only +No type information for this code. +No type information for this code.=== /k.ts === +const enum K { One, Two } +>K : Symbol(K, Decl(k.ts, 0, 0)) +>One : Symbol(K.One, Decl(k.ts, 0, 14)) +>Two : Symbol(K.Two, Decl(k.ts, 0, 19)) + +export = K; +>K : Symbol(K, Decl(k.ts, 0, 0)) + +=== /l.ts === +import K = require('./k'); +>K : Symbol(K, Decl(l.ts, 0, 0)) + +K.One; +>K.One : Symbol(K.One, Decl(k.ts, 0, 14)) +>K : Symbol(K, Decl(l.ts, 0, 0)) +>One : Symbol(K.One, Decl(k.ts, 0, 14)) + +=== /j.ts === +// Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/importsNotUsedAsValues_error.types b/tests/baselines/reference/importsNotUsedAsValues_error.types index c7f0eb86ad..cbe4fc6270 100644 --- a/tests/baselines/reference/importsNotUsedAsValues_error.types +++ b/tests/baselines/reference/importsNotUsedAsValues_error.types @@ -128,3 +128,49 @@ console.log(c, d); >c : C >d : C.Two +=== /h.ts === +class H {} +>H : H + +export = H; +>H : H + +=== /i.ts === +import H = require('./h'); // Error +>H : typeof H + +let h: H = {}; +>h : H +>{} : {} + +console.log(h); +>console.log(h) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>h : H + +=== /j.ts === +import H = require('./h'); // noUnusedLocals error only +No type information for this code. +No type information for this code.=== /k.ts === +const enum K { One, Two } +>K : K +>One : K.One +>Two : K.Two + +export = K; +>K : K + +=== /l.ts === +import K = require('./k'); +>K : typeof K + +K.One; +>K.One : K.One +>K : typeof K +>One : K.One + +=== /j.ts === +// Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 +No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/tscWatch/programUpdates/updates-diagnostics-and-emit-for-decorators.js b/tests/baselines/reference/tscWatch/programUpdates/updates-diagnostics-and-emit-for-decorators.js index 8fa5d8b885..7d8fe90cb8 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/updates-diagnostics-and-emit-for-decorators.js +++ b/tests/baselines/reference/tscWatch/programUpdates/updates-diagnostics-and-emit-for-decorators.js @@ -31,7 +31,7 @@ Output:: >> Screen clear [12:00:15 AM] Starting compilation in watch mode... -a.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +a.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. 1 import {B} from './b'   ~~~~~~~~~~~~~~~~~~~~~ @@ -110,7 +110,7 @@ Output:: >> Screen clear [12:00:23 AM] File change detected. Starting incremental compilation... -a.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +a.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. 1 import {B} from './b'   ~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/tscWatch/programUpdates/updates-errors-and-emit-when-importsNotUsedAsValues-changes.js b/tests/baselines/reference/tscWatch/programUpdates/updates-errors-and-emit-when-importsNotUsedAsValues-changes.js index 0bea4e7d87..494fa61843 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/updates-errors-and-emit-when-importsNotUsedAsValues-changes.js +++ b/tests/baselines/reference/tscWatch/programUpdates/updates-errors-and-emit-when-importsNotUsedAsValues-changes.js @@ -148,7 +148,7 @@ Output:: >> Screen clear [12:00:43 AM] File change detected. Starting incremental compilation... -b.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because the 'importsNotUsedAsValues' is set to 'error'. +b.ts:1:1 - error TS1371: This import is never used as a value and must use 'import type' because 'importsNotUsedAsValues' is set to 'error'. 1 import {C} from './a';   ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/cases/conformance/externalModules/typeOnly/cjsImportInES2015.ts b/tests/cases/conformance/externalModules/typeOnly/cjsImportInES2015.ts new file mode 100644 index 0000000000..bcc9b5ab31 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/cjsImportInES2015.ts @@ -0,0 +1,10 @@ +// @module: es2015 +// @moduleResolution: node + +// @Filename: /project/node_modules/cjs-dep/index.d.ts +declare class SpecialError extends Error {} +export = SpecialError; + +// @Filename: /project/index.ts +import type SpecialError = require("cjs-dep"); +function handleError(err: SpecialError) {} diff --git a/tests/cases/conformance/externalModules/typeOnly/grammarErrors.ts b/tests/cases/conformance/externalModules/typeOnly/grammarErrors.ts index e16efa45f9..caec1c7284 100644 --- a/tests/cases/conformance/externalModules/typeOnly/grammarErrors.ts +++ b/tests/cases/conformance/externalModules/typeOnly/grammarErrors.ts @@ -13,3 +13,9 @@ import type A, { B, C } from './a'; // @Filename: /a.js import type A from './a'; export type { A }; + +// @Filename: /c.ts +namespace ns { + export class Foo {} +} +import type Foo = ns.Foo; diff --git a/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclaration.ts b/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclaration.ts new file mode 100644 index 0000000000..29870a7880 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclaration.ts @@ -0,0 +1,19 @@ +// @noTypesAndSymbols: true +// @declaration: true + +// @Filename: /a.ts +class A { a!: string } +export = A; + +// @Filename: /b.ts +class SomeClass {} +export = SomeClass; + +// @Filename: /c.ts +import type A = require('./a'); // Ok +import type = require('./b'); // Ok + +A.prototype; // Error +const a: A = { a: 'a' }; // Ok +void type; // Ok +export declare const AConstructor: typeof A; // Ok diff --git a/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclarationError.ts b/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclarationError.ts deleted file mode 100644 index f3b40cd48d..0000000000 --- a/tests/cases/conformance/externalModules/typeOnly/importEqualsDeclarationError.ts +++ /dev/null @@ -1,14 +0,0 @@ -// @noEmit: true -// @noTypesAndSymbols: true - -// @Filename: /a.ts -type T = {}; -export = T; - -// @Filename: /b.ts -class SomeClass {} -export = SomeClass; - -// @Filename: /c.ts -import type T = require('./a'); // Error -import type = require('./b'); // Ok diff --git a/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts b/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts index aa67936654..ae697e7c3c 100644 --- a/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts +++ b/tests/cases/conformance/externalModules/typeOnly/importsNotUsedAsValues_error.ts @@ -40,4 +40,27 @@ console.log(c, d); import { C } from './a'; let c: C; let d: C.Two; -console.log(c, d); \ No newline at end of file +console.log(c, d); + +// @Filename: /h.ts +class H {} +export = H; + +// @Filename: /i.ts +import H = require('./h'); // Error +let h: H = {}; +console.log(h); + +// @Filename: /j.ts +import H = require('./h'); // noUnusedLocals error only + +// @Filename: /k.ts +const enum K { One, Two } +export = K; + +// @Filename: /l.ts +import K = require('./k'); +K.One; + +// @Filename: /j.ts +// Sad face https://github.com/microsoft/TypeScript/blob/6b04f5039429b9d412696fe2febe39ecc69ad365/src/testRunner/compilerRunner.ts#L207 \ No newline at end of file