diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8cfe95524eae0..a1c2edb860a46 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2191,17 +2191,25 @@ namespace ts { const message = isExport ? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type : Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type; - const relatedMessage = isExport - ? Diagnostics._0_was_exported_here - : Diagnostics._0_was_imported_here; const unescapedName = unescapeLeadingUnderscores(name); - addRelatedInfo( + addTypeOnlyDeclarationRelatedInfo( error(useSite, message, unescapedName), - createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, unescapedName)); + typeOnlyDeclaration, + unescapedName); } } } + function addTypeOnlyDeclarationRelatedInfo(diagnostic: Diagnostic, typeOnlyDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, unescapedName: string) { + if (!typeOnlyDeclaration) return diagnostic; + return addRelatedInfo( + diagnostic, + createDiagnosticForNode( + typeOnlyDeclaration, + typeOnlyDeclarationIsExport(typeOnlyDeclaration) ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here, + unescapedName)); + } + function getIsDeferredContext(location: Node, lastLocation: Node | undefined): boolean { if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) { // initializers in instance property declaration of class like entities are executed in constructor and thus deferred @@ -38599,13 +38607,49 @@ namespace ts { error(node, message, symbolToString(symbol)); } - // Don't allow to re-export something with no value side when `--isolatedModules` is set. if (compilerOptions.isolatedModules - && node.kind === SyntaxKind.ExportSpecifier - && !node.parent.parent.isTypeOnly - && !(target.flags & SymbolFlags.Value) + && !isTypeOnlyImportOrExportDeclaration(node) && !(node.flags & NodeFlags.Ambient)) { - error(node, Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type); + const typeOnlyAlias = getTypeOnlyAliasDeclaration(symbol); + const isType = !(target.flags & SymbolFlags.Value); + if (isType || typeOnlyAlias) { + switch (node.kind) { + case SyntaxKind.ImportClause: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: { + if (compilerOptions.preserveValueImports) { + Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name"); + const message = isType + ? Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled + : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled; + const name = idText(node.kind === SyntaxKind.ImportSpecifier ? node.propertyName || node.name : node.name); + addTypeOnlyDeclarationRelatedInfo( + error(node, message, name), + isType ? undefined : typeOnlyAlias, + name + ); + } + break; + } + case SyntaxKind.ExportSpecifier: { + // Don't allow re-exporting an export that will be elided when `--isolatedModules` is set. + // The exception is that `import type { A } from './a'; export { A }` is allowed + // because single-file analysis can determine that the export should be dropped. + if (getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node)) { + const message = isType + ? Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type + : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_isolatedModules_is_enabled; + const name = idText(node.propertyName || node.name); + addTypeOnlyDeclarationRelatedInfo( + error(node, message, name), + isType ? undefined : typeOnlyAlias, + name + ); + return; + } + } + } + } } if (isImportSpecifier(node) && target.declarations?.every(d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated))) { @@ -40386,13 +40430,13 @@ namespace ts { function isValueAliasDeclaration(node: Node): boolean { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: - return isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol); + return isAliasResolvedToValue(getSymbolOfNode(node)); case SyntaxKind.ImportClause: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - const symbol = getSymbolOfNode(node) || unknownSymbol; - return isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol); + const symbol = getSymbolOfNode(node); + return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol); case SyntaxKind.ExportDeclaration: const exportClause = (node as ExportDeclaration).exportClause; return !!exportClause && ( @@ -40401,7 +40445,7 @@ namespace ts { ); case SyntaxKind.ExportAssignment: return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ? - isAliasResolvedToValue(getSymbolOfNode(node) || unknownSymbol) : + isAliasResolvedToValue(getSymbolOfNode(node)) : true; } return false; @@ -40418,7 +40462,10 @@ namespace ts { return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } - function isAliasResolvedToValue(symbol: Symbol): boolean { + function isAliasResolvedToValue(symbol: Symbol | undefined): boolean { + if (!symbol) { + return false; + } const target = resolveAlias(symbol); if (target === unknownSymbol) { return true; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 8ea829eaad5b2..22e784391a1c7 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -570,7 +570,7 @@ namespace ts { type: new Map(getEntries({ remove: ImportsNotUsedAsValues.Remove, preserve: ImportsNotUsedAsValues.Preserve, - error: ImportsNotUsedAsValues.Error + error: ImportsNotUsedAsValues.Error, })), affectsEmit: true, affectsSemanticDiagnostics: true, @@ -1168,6 +1168,14 @@ namespace ts { description: Diagnostics.Emit_ECMAScript_standard_compliant_class_fields, defaultValueDescription: "false" }, + { + name: "preserveValueImports", + type: "boolean", + affectsEmit: true, + category: Diagnostics.Emit, + description: Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed, + }, + { name: "keyofStringsOnly", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 91780f5309c8d..a6bb05d949ea3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1408,6 +1408,22 @@ "category": "Error", "code": 1443 }, + "'{0}' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled.": { + "category": "Error", + "code": 1444 + }, + "'{0}' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled.": { + "category": "Error", + "code": 1446 + }, + "'{0}' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled.": { + "category": "Error", + "code": 1448 + }, + "Preserve unused imported values in the JavaScript output that would otherwise be removed.": { + "category": "Message", + "code": 1449 + }, "The types of '{0}' are incompatible between these types.": { "category": "Error", @@ -4038,6 +4054,10 @@ "category": "Error", "code": 5094 }, + "Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later.": { + "category": "Error", + "code": 5095 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 81539867f51bc..d20ac90d49e68 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3307,6 +3307,10 @@ namespace ts { } } + if (options.preserveValueImports && getEmitModuleKind(options) < ModuleKind.ES2015) { + createOptionValueDiagnostic("importsNotUsedAsValues", Diagnostics.Option_preserveValueImports_can_only_be_used_when_module_is_set_to_es2015_or_later); + } + // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files if (!options.noEmit && !options.suppressOutputPathCheck) { const emitHost = getEmitHost(); @@ -3577,7 +3581,7 @@ namespace ts { createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2, option3); } - function createOptionValueDiagnostic(option1: string, message: DiagnosticMessage, arg0: string) { + function createOptionValueDiagnostic(option1: string, message: DiagnosticMessage, arg0?: string) { createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0); } @@ -3592,7 +3596,7 @@ namespace ts { } } - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) { + function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1, arg2); @@ -3618,7 +3622,7 @@ namespace ts { return _compilerOptionsObjectLiteralSyntax || undefined; } - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean { + function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): boolean { const props = getPropertyAssignment(objectLiteral, key1, key2); for (const prop of props) { programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2)); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 21a0ec59f101b..012be39dadbdd 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2791,7 +2791,7 @@ namespace ts { } /** - * Visits an import declaration, eliding it if it is not referenced and `importsNotUsedAsValues` is not 'preserve'. + * Visits an import declaration, eliding it if it is type-only or if it has an import clause that may be elided. * * @param node The import declaration node. */ @@ -2821,29 +2821,27 @@ namespace ts { } /** - * Visits an import clause, eliding it if it is not referenced. + * Visits an import clause, eliding it if its `name` and `namedBindings` may both be elided. * * @param node The import clause node. */ function visitImportClause(node: ImportClause): VisitResult { - if (node.isTypeOnly) { - return undefined; - } + Debug.assert(!node.isTypeOnly); // Elide the import clause if we elide both its name and its named bindings. - const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined; + const name = shouldEmitAliasDeclaration(node) ? node.name : undefined; const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings); return (name || namedBindings) ? factory.updateImportClause(node, /*isTypeOnly*/ false, name, namedBindings) : undefined; } /** - * Visits named import bindings, eliding it if it is not referenced. + * Visits named import bindings, eliding them if their targets, their references, and the compilation settings allow. * * @param node The named import bindings node. */ function visitNamedImportBindings(node: NamedImportBindings): VisitResult { if (node.kind === SyntaxKind.NamespaceImport) { // Elide a namespace import if it is not referenced. - return resolver.isReferencedAliasDeclaration(node) ? node : undefined; + return shouldEmitAliasDeclaration(node) ? node : undefined; } else { // Elide named imports if all of its import specifiers are elided. @@ -2853,13 +2851,12 @@ namespace ts { } /** - * Visits an import specifier, eliding it if it is not referenced. + * Visits an import specifier, eliding it if its target, its references, and the compilation settings allow. * * @param node The import specifier node. */ function visitImportSpecifier(node: ImportSpecifier): VisitResult { - // Elide an import specifier if it is not referenced. - return resolver.isReferencedAliasDeclaration(node) ? node : undefined; + return shouldEmitAliasDeclaration(node) ? node : undefined; } /** @@ -2876,8 +2873,7 @@ namespace ts { } /** - * Visits an export declaration, eliding it if it does not contain a clause that resolves - * to a value. + * Visits an export declaration, eliding it if it does not contain a clause that resolves to a value. * * @param node The export declaration node. */ @@ -2950,7 +2946,7 @@ namespace ts { // preserve old compiler's behavior: emit 'var' for import declaration (even if we do not consider them referenced) when // - current file is not external module // - import declaration is top level and target is value imported by entity name - return resolver.isReferencedAliasDeclaration(node) + return shouldEmitAliasDeclaration(node) || (!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node)); } @@ -2967,7 +2963,7 @@ namespace ts { } if (isExternalModuleImportEqualsDeclaration(node)) { - const isReferenced = resolver.isReferencedAliasDeclaration(node); + const isReferenced = shouldEmitAliasDeclaration(node); // If the alias is unreferenced but we want to keep the import, replace with 'import "mod"'. if (!isReferenced && compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Preserve) { return setOriginalNode( @@ -3358,5 +3354,11 @@ namespace ts { return isPropertyAccessExpression(node) || isElementAccessExpression(node) ? resolver.getConstantValue(node) : undefined; } + + function shouldEmitAliasDeclaration(node: Node): boolean { + return compilerOptions.preserveValueImports + ? resolver.isValueAliasDeclaration(node) + : resolver.isReferencedAliasDeclaration(node); + } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d055b91a93a5e..544fc01580fa3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3104,6 +3104,14 @@ namespace ts { | ImportOrExportSpecifier ; + export type TypeOnlyAliasDeclaration = + | ImportClause & { readonly isTypeOnly: true, readonly name: Identifier } + | ImportEqualsDeclaration & { readonly isTypeOnly: true } + | NamespaceImport & { readonly parent: ImportClause & { readonly isTypeOnly: true } } + | ImportSpecifier & { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true } } } + | ExportSpecifier & { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } } + ; + /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -6049,6 +6057,7 @@ namespace ts { preserveConstEnums?: boolean; noImplicitOverride?: boolean; preserveSymlinks?: boolean; + preserveValueImports?: boolean; /* @internal */ preserveWatchOutput?: boolean; project?: string; /* @internal */ pretty?: boolean; @@ -6142,7 +6151,7 @@ namespace ts { export const enum ImportsNotUsedAsValues { Remove, Preserve, - Error + Error, } export const enum NewLineKind { diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index b9236521cba67..91b0a1cc9a9cc 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1126,7 +1126,7 @@ namespace ts { return isImportSpecifier(node) || isExportSpecifier(node); } - export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration { + export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration { switch (node.kind) { case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 14de9571dc63a..3516993b2d5ae 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1688,6 +1688,28 @@ declare namespace ts { } export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; export type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; + export type TypeOnlyAliasDeclaration = ImportClause & { + readonly isTypeOnly: true; + readonly name: Identifier; + } | ImportEqualsDeclaration & { + readonly isTypeOnly: true; + } | NamespaceImport & { + readonly parent: ImportClause & { + readonly isTypeOnly: true; + }; + } | ImportSpecifier & { + readonly parent: NamedImports & { + readonly parent: ImportClause & { + readonly isTypeOnly: true; + }; + }; + } | ExportSpecifier & { + readonly parent: NamedExports & { + readonly parent: ExportDeclaration & { + readonly isTypeOnly: true; + }; + }; + }; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -2904,6 +2926,7 @@ declare namespace ts { preserveConstEnums?: boolean; noImplicitOverride?: boolean; preserveSymlinks?: boolean; + preserveValueImports?: boolean; project?: string; reactNamespace?: string; jsxFactory?: string; @@ -4319,7 +4342,7 @@ declare namespace ts { function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; - function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration; + function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration; function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index a83b83826341f..76913e5b2a49b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1688,6 +1688,28 @@ declare namespace ts { } export type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; export type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; + export type TypeOnlyAliasDeclaration = ImportClause & { + readonly isTypeOnly: true; + readonly name: Identifier; + } | ImportEqualsDeclaration & { + readonly isTypeOnly: true; + } | NamespaceImport & { + readonly parent: ImportClause & { + readonly isTypeOnly: true; + }; + } | ImportSpecifier & { + readonly parent: NamedImports & { + readonly parent: ImportClause & { + readonly isTypeOnly: true; + }; + }; + } | ExportSpecifier & { + readonly parent: NamedExports & { + readonly parent: ExportDeclaration & { + readonly isTypeOnly: true; + }; + }; + }; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -2904,6 +2926,7 @@ declare namespace ts { preserveConstEnums?: boolean; noImplicitOverride?: boolean; preserveSymlinks?: boolean; + preserveValueImports?: boolean; project?: string; reactNamespace?: string; jsxFactory?: string; @@ -4319,7 +4342,7 @@ declare namespace ts { function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken; function isTemplateMiddleOrTemplateTail(node: Node): node is TemplateMiddle | TemplateTail; function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | ExportSpecifier; - function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyCompatibleAliasDeclaration; + function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration; function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; function isModifier(node: Node): node is Modifier; function isEntityName(node: Node): node is EntityName; diff --git a/tests/baselines/reference/isolatedModulesReExportType.errors.txt b/tests/baselines/reference/isolatedModulesReExportType.errors.txt index 299bd0fcf88e6..3d89ddf487a53 100644 --- a/tests/baselines/reference/isolatedModulesReExportType.errors.txt +++ b/tests/baselines/reference/isolatedModulesReExportType.errors.txt @@ -1,8 +1,9 @@ /user.ts(2,10): error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. /user.ts(17,10): error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. +/user.ts(25,10): error TS1448: 'CC' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled. -==== /user.ts (2 errors) ==== +==== /user.ts (3 errors) ==== // Error, can't re-export something that's only a type. export { T } from "./exportT"; ~ @@ -25,6 +26,17 @@ ~~~~~~~ !!! error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. + // Ok, type-only import indicates that the export can be elided. + import type { T as TT } from "./exportT"; + export { TT }; + + // Error, type-only declaration is in a different file. + import { C as CC } from "./reExportValueAsTypeOnly"; + export { CC }; + ~~ +!!! error TS1448: 'CC' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled. +!!! related TS1377 /reExportValueAsTypeOnly.ts:1:15: 'CC' was exported here. + ==== /exportT.ts (0 errors) ==== export type T = number; @@ -45,4 +57,7 @@ declare module "baz" { export { T } from "foo"; // Also allowed. } + +==== /reExportValueAsTypeOnly.ts (0 errors) ==== + export type { C } from "./exportValue"; \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesReExportType.js b/tests/baselines/reference/isolatedModulesReExportType.js index 9908e6701dffe..2e3828fcfbb8d 100644 --- a/tests/baselines/reference/isolatedModulesReExportType.js +++ b/tests/baselines/reference/isolatedModulesReExportType.js @@ -21,6 +21,9 @@ declare module "baz" { export { T } from "foo"; // Also allowed. } +//// [reExportValueAsTypeOnly.ts] +export type { C } from "./exportValue"; + //// [user.ts] // Error, can't re-export something that's only a type. export { T } from "./exportT"; @@ -39,6 +42,14 @@ export type T3 = T; // Error, not clear (to an isolated module) whether `T4` is a type. import { T } from "./exportT"; export { T as T4 }; + +// Ok, type-only import indicates that the export can be elided. +import type { T as TT } from "./exportT"; +export { TT }; + +// Error, type-only declaration is in a different file. +import { C as CC } from "./reExportValueAsTypeOnly"; +export { CC }; //// [exportT.js] @@ -57,6 +68,9 @@ var C = /** @class */ (function () { return C; }()); exports.C = C; +//// [reExportValueAsTypeOnly.js] +"use strict"; +exports.__esModule = true; //// [user.js] "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { diff --git a/tests/baselines/reference/isolatedModulesReExportType.symbols b/tests/baselines/reference/isolatedModulesReExportType.symbols index b64f0cae4626a..e52acba684931 100644 --- a/tests/baselines/reference/isolatedModulesReExportType.symbols +++ b/tests/baselines/reference/isolatedModulesReExportType.symbols @@ -30,6 +30,22 @@ export { T as T4 }; >T : Symbol(T, Decl(user.ts, 15, 8)) >T4 : Symbol(T4, Decl(user.ts, 16, 8)) +// Ok, type-only import indicates that the export can be elided. +import type { T as TT } from "./exportT"; +>T : Symbol(NS.T, Decl(exportT.ts, 0, 0)) +>TT : Symbol(TT, Decl(user.ts, 19, 13)) + +export { TT }; +>TT : Symbol(TT, Decl(user.ts, 20, 8)) + +// Error, type-only declaration is in a different file. +import { C as CC } from "./reExportValueAsTypeOnly"; +>C : Symbol(C, Decl(reExportValueAsTypeOnly.ts, 0, 13)) +>CC : Symbol(CC, Decl(user.ts, 23, 8)) + +export { CC }; +>CC : Symbol(CC, Decl(user.ts, 24, 8)) + === /exportT.ts === export type T = number; >T : Symbol(T, Decl(exportT.ts, 0, 0)) @@ -45,3 +61,7 @@ declare type T = number; export = T; >T : Symbol(T, Decl(exportEqualsT.ts, 0, 0)) +=== /reExportValueAsTypeOnly.ts === +export type { C } from "./exportValue"; +>C : Symbol(C, Decl(reExportValueAsTypeOnly.ts, 0, 13)) + diff --git a/tests/baselines/reference/isolatedModulesReExportType.types b/tests/baselines/reference/isolatedModulesReExportType.types index 55c4cdfb7b778..370853c76aee5 100644 --- a/tests/baselines/reference/isolatedModulesReExportType.types +++ b/tests/baselines/reference/isolatedModulesReExportType.types @@ -8,7 +8,7 @@ export import T2 = require("./exportEqualsT"); // OK, has a value side export { C } from "./exportValue"; ->C : typeof import("/exportValue").C +>C : typeof CC // OK, even though the namespace it exports is only types. import * as NS from "./exportT"; @@ -29,6 +29,22 @@ export { T as T4 }; >T : any >T4 : any +// Ok, type-only import indicates that the export can be elided. +import type { T as TT } from "./exportT"; +>T : any +>TT : number + +export { TT }; +>TT : any + +// Error, type-only declaration is in a different file. +import { C as CC } from "./reExportValueAsTypeOnly"; +>C : typeof CC +>CC : typeof CC + +export { CC }; +>CC : typeof CC + === /exportT.ts === export type T = number; >T : number @@ -44,3 +60,7 @@ declare type T = number; export = T; >T : number +=== /reExportValueAsTypeOnly.ts === +export type { C } from "./exportValue"; +>C : import("/exportValue").C + diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=false).errors.txt b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).errors.txt new file mode 100644 index 0000000000000..681847a43c64a --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/externalModules/typeOnly/d.ts(1,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. +tests/cases/conformance/externalModules/typeOnly/e.ts(1,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +tests/cases/conformance/externalModules/typeOnly/e.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ==== + export default {}; + export const b = 0; + export const c = 1; + export interface D {} + +==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ==== + import a, { b, c, D } from "./a"; + +==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ==== + import * as a from "./a"; + +==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ==== + export = {}; + ~~~~~~~~~~~~ +!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. + +==== tests/cases/conformance/externalModules/typeOnly/e.ts (2 errors) ==== + import D = require("./d"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + import DD = require("./d"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + DD; + +==== tests/cases/conformance/externalModules/typeOnly/f.ts (0 errors) ==== + import type a from "./a"; + import { b, c } from "./a"; + b; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=false).js b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).js new file mode 100644 index 0000000000000..9b26f77b33145 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).js @@ -0,0 +1,44 @@ +//// [tests/cases/conformance/externalModules/typeOnly/preserveValueImports.ts] //// + +//// [a.ts] +export default {}; +export const b = 0; +export const c = 1; +export interface D {} + +//// [b.ts] +import a, { b, c, D } from "./a"; + +//// [c.ts] +import * as a from "./a"; + +//// [d.ts] +export = {}; + +//// [e.ts] +import D = require("./d"); +import DD = require("./d"); +DD; + +//// [f.ts] +import type a from "./a"; +import { b, c } from "./a"; +b; + + +//// [a.js] +export default {}; +export var b = 0; +export var c = 1; +//// [b.js] +import a, { b, c } from "./a"; +//// [c.js] +import * as a from "./a"; +//// [d.js] +export {}; +//// [e.js] +DD; +export {}; +//// [f.js] +import { b, c } from "./a"; +b; diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=false).symbols b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).symbols new file mode 100644 index 0000000000000..d8d8fcc5927e5 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).symbols @@ -0,0 +1,46 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export default {}; +export const b = 0; +>b : Symbol(b, Decl(a.ts, 1, 12)) + +export const c = 1; +>c : Symbol(c, Decl(a.ts, 2, 12)) + +export interface D {} +>D : Symbol(D, Decl(a.ts, 2, 19)) + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +import a, { b, c, D } from "./a"; +>a : Symbol(a, Decl(b.ts, 0, 6)) +>b : Symbol(b, Decl(b.ts, 0, 11)) +>c : Symbol(c, Decl(b.ts, 0, 14)) +>D : Symbol(D, Decl(b.ts, 0, 17)) + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import * as a from "./a"; +>a : Symbol(a, Decl(c.ts, 0, 6)) + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export = {}; +No type information for this code. +No type information for this code.=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import D = require("./d"); +>D : Symbol(D, Decl(e.ts, 0, 0)) + +import DD = require("./d"); +>DD : Symbol(DD, Decl(e.ts, 0, 26)) + +DD; +>DD : Symbol(DD, Decl(e.ts, 0, 26)) + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type a from "./a"; +>a : Symbol(a, Decl(f.ts, 0, 6)) + +import { b, c } from "./a"; +>b : Symbol(b, Decl(f.ts, 1, 8)) +>c : Symbol(c, Decl(f.ts, 1, 11)) + +b; +>b : Symbol(b, Decl(f.ts, 1, 8)) + diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=false).types b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).types new file mode 100644 index 0000000000000..d36e2a2a0f9f2 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=false).types @@ -0,0 +1,50 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export default {}; +>{} : {} + +export const b = 0; +>b : 0 +>0 : 0 + +export const c = 1; +>c : 1 +>1 : 1 + +export interface D {} + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +import a, { b, c, D } from "./a"; +>a : {} +>b : 0 +>c : 1 +>D : any + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import * as a from "./a"; +>a : typeof a + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export = {}; +>{} : {} + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import D = require("./d"); +>D : {} + +import DD = require("./d"); +>DD : {} + +DD; +>DD : {} + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type a from "./a"; +>a : any + +import { b, c } from "./a"; +>b : 0 +>c : 1 + +b; +>b : 0 + diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=true).errors.txt b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).errors.txt new file mode 100644 index 0000000000000..aac66e08f6458 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/externalModules/typeOnly/b.ts(1,19): error TS1444: 'D' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/d.ts(1,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. +tests/cases/conformance/externalModules/typeOnly/e.ts(1,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. +tests/cases/conformance/externalModules/typeOnly/e.ts(2,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + + +==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ==== + export default {}; + export const b = 0; + export const c = 1; + export interface D {} + +==== tests/cases/conformance/externalModules/typeOnly/b.ts (1 errors) ==== + import a, { b, c, D } from "./a"; + ~ +!!! error TS1444: 'D' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. + +==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ==== + import * as a from "./a"; + +==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ==== + export = {}; + ~~~~~~~~~~~~ +!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. + +==== tests/cases/conformance/externalModules/typeOnly/e.ts (2 errors) ==== + import D = require("./d"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + import DD = require("./d"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead. + DD; + +==== tests/cases/conformance/externalModules/typeOnly/f.ts (0 errors) ==== + import type a from "./a"; + import { b, c } from "./a"; + b; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=true).js b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).js new file mode 100644 index 0000000000000..9b26f77b33145 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).js @@ -0,0 +1,44 @@ +//// [tests/cases/conformance/externalModules/typeOnly/preserveValueImports.ts] //// + +//// [a.ts] +export default {}; +export const b = 0; +export const c = 1; +export interface D {} + +//// [b.ts] +import a, { b, c, D } from "./a"; + +//// [c.ts] +import * as a from "./a"; + +//// [d.ts] +export = {}; + +//// [e.ts] +import D = require("./d"); +import DD = require("./d"); +DD; + +//// [f.ts] +import type a from "./a"; +import { b, c } from "./a"; +b; + + +//// [a.js] +export default {}; +export var b = 0; +export var c = 1; +//// [b.js] +import a, { b, c } from "./a"; +//// [c.js] +import * as a from "./a"; +//// [d.js] +export {}; +//// [e.js] +DD; +export {}; +//// [f.js] +import { b, c } from "./a"; +b; diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=true).symbols b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).symbols new file mode 100644 index 0000000000000..d8d8fcc5927e5 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).symbols @@ -0,0 +1,46 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export default {}; +export const b = 0; +>b : Symbol(b, Decl(a.ts, 1, 12)) + +export const c = 1; +>c : Symbol(c, Decl(a.ts, 2, 12)) + +export interface D {} +>D : Symbol(D, Decl(a.ts, 2, 19)) + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +import a, { b, c, D } from "./a"; +>a : Symbol(a, Decl(b.ts, 0, 6)) +>b : Symbol(b, Decl(b.ts, 0, 11)) +>c : Symbol(c, Decl(b.ts, 0, 14)) +>D : Symbol(D, Decl(b.ts, 0, 17)) + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import * as a from "./a"; +>a : Symbol(a, Decl(c.ts, 0, 6)) + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export = {}; +No type information for this code. +No type information for this code.=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import D = require("./d"); +>D : Symbol(D, Decl(e.ts, 0, 0)) + +import DD = require("./d"); +>DD : Symbol(DD, Decl(e.ts, 0, 26)) + +DD; +>DD : Symbol(DD, Decl(e.ts, 0, 26)) + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type a from "./a"; +>a : Symbol(a, Decl(f.ts, 0, 6)) + +import { b, c } from "./a"; +>b : Symbol(b, Decl(f.ts, 1, 8)) +>c : Symbol(c, Decl(f.ts, 1, 11)) + +b; +>b : Symbol(b, Decl(f.ts, 1, 8)) + diff --git a/tests/baselines/reference/preserveValueImports(isolatedmodules=true).types b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).types new file mode 100644 index 0000000000000..d36e2a2a0f9f2 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports(isolatedmodules=true).types @@ -0,0 +1,50 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export default {}; +>{} : {} + +export const b = 0; +>b : 0 +>0 : 0 + +export const c = 1; +>c : 1 +>1 : 1 + +export interface D {} + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +import a, { b, c, D } from "./a"; +>a : {} +>b : 0 +>c : 1 +>D : any + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import * as a from "./a"; +>a : typeof a + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export = {}; +>{} : {} + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import D = require("./d"); +>D : {} + +import DD = require("./d"); +>DD : {} + +DD; +>DD : {} + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type a from "./a"; +>a : any + +import { b, c } from "./a"; +>b : 0 +>c : 1 + +b; +>b : 0 + diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).js b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).js new file mode 100644 index 0000000000000..36507e663afc9 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).js @@ -0,0 +1,73 @@ +//// [tests/cases/conformance/externalModules/typeOnly/preserveValueImports_errors.ts] //// + +//// [a.ts] +export type A = {}; +export type { A as default }; + +//// [b.ts] +class B {}; +export type { B, B as default }; + +//// [c.ts] +import DefaultA from "./a"; +import { A } from "./a"; +import DefaultB from "./b"; +import { B } from "./b"; + +//// [c.fixed.ts] +import type DefaultA from "./a"; +import type { A } from "./a"; +import type DefaultB from "./b"; +import type { B } from "./b"; + +//// [d.ts] +export { A as AA } from "./a"; +export { B as BB } from "./b"; + +//// [d.fixed.ts] +export type { A as AA } from "./a"; +export type { B as BB } from "./b"; + +//// [e.ts] +import { AA, BB } from "./d"; + +//// [e.fixed.ts] +import type { AA, BB } from "./d"; + +//// [f.ts] +import type { A } from "./a"; +import type { B } from "./b"; +export { A, B as BB }; + +//// [f.fixed.ts] +import type { A } from "./a"; +import type { B } from "./b"; +export type { A, B as BB }; + + +//// [a.js] +export {}; +//// [b.js] +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +; +export {}; +//// [c.js] +export {}; +//// [c.fixed.js] +export {}; +//// [d.js] +export {}; +//// [d.fixed.js] +export {}; +//// [e.js] +export {}; +//// [e.fixed.js] +export {}; +//// [f.js] +export {}; +//// [f.fixed.js] +export {}; diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).symbols b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).symbols new file mode 100644 index 0000000000000..0dd64238caf2a --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).symbols @@ -0,0 +1,95 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export type A = {}; +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export type { A as default }; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>default : Symbol(default, Decl(a.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +class B {}; +>B : Symbol(B, Decl(b.ts, 0, 0)) + +export type { B, B as default }; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>B : Symbol(B, Decl(b.ts, 0, 0)) +>default : Symbol(default, Decl(b.ts, 1, 16)) + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import DefaultA from "./a"; +>DefaultA : Symbol(DefaultA, Decl(c.ts, 0, 6)) + +import { A } from "./a"; +>A : Symbol(A, Decl(c.ts, 1, 8)) + +import DefaultB from "./b"; +>DefaultB : Symbol(DefaultB, Decl(c.ts, 2, 6)) + +import { B } from "./b"; +>B : Symbol(B, Decl(c.ts, 3, 8)) + +=== tests/cases/conformance/externalModules/typeOnly/c.fixed.ts === +import type DefaultA from "./a"; +>DefaultA : Symbol(DefaultA, Decl(c.fixed.ts, 0, 6)) + +import type { A } from "./a"; +>A : Symbol(A, Decl(c.fixed.ts, 1, 13)) + +import type DefaultB from "./b"; +>DefaultB : Symbol(DefaultB, Decl(c.fixed.ts, 2, 6)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(c.fixed.ts, 3, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export { A as AA } from "./a"; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>AA : Symbol(AA, Decl(d.ts, 0, 8)) + +export { B as BB } from "./b"; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>BB : Symbol(BB, Decl(d.ts, 1, 8)) + +=== tests/cases/conformance/externalModules/typeOnly/d.fixed.ts === +export type { A as AA } from "./a"; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>AA : Symbol(AA, Decl(d.fixed.ts, 0, 13)) + +export type { B as BB } from "./b"; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>BB : Symbol(BB, Decl(d.fixed.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import { AA, BB } from "./d"; +>AA : Symbol(AA, Decl(e.ts, 0, 8)) +>BB : Symbol(BB, Decl(e.ts, 0, 12)) + +=== tests/cases/conformance/externalModules/typeOnly/e.fixed.ts === +import type { AA, BB } from "./d"; +>AA : Symbol(AA, Decl(e.fixed.ts, 0, 13)) +>BB : Symbol(BB, Decl(e.fixed.ts, 0, 17)) + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type { A } from "./a"; +>A : Symbol(A, Decl(f.ts, 0, 13)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(f.ts, 1, 13)) + +export { A, B as BB }; +>A : Symbol(A, Decl(f.ts, 2, 8)) +>B : Symbol(B, Decl(f.ts, 1, 13)) +>BB : Symbol(BB, Decl(f.ts, 2, 11)) + +=== tests/cases/conformance/externalModules/typeOnly/f.fixed.ts === +import type { A } from "./a"; +>A : Symbol(A, Decl(f.fixed.ts, 0, 13)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(f.fixed.ts, 1, 13)) + +export type { A, B as BB }; +>A : Symbol(A, Decl(f.fixed.ts, 2, 13)) +>B : Symbol(B, Decl(f.fixed.ts, 1, 13)) +>BB : Symbol(BB, Decl(f.fixed.ts, 2, 16)) + diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).types b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).types new file mode 100644 index 0000000000000..1e8a912ed7ced --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=false).types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export type A = {}; +>A : A + +export type { A as default }; +>A : any +>default : A + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +class B {}; +>B : B + +export type { B, B as default }; +>B : B +>B : typeof B +>default : B + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import DefaultA from "./a"; +>DefaultA : any + +import { A } from "./a"; +>A : any + +import DefaultB from "./b"; +>DefaultB : typeof DefaultB + +import { B } from "./b"; +>B : typeof DefaultB + +=== tests/cases/conformance/externalModules/typeOnly/c.fixed.ts === +import type DefaultA from "./a"; +>DefaultA : DefaultA + +import type { A } from "./a"; +>A : DefaultA + +import type DefaultB from "./b"; +>DefaultB : DefaultB + +import type { B } from "./b"; +>B : DefaultB + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export { A as AA } from "./a"; +>A : any +>AA : any + +export { B as BB } from "./b"; +>B : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B +>BB : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B + +=== tests/cases/conformance/externalModules/typeOnly/d.fixed.ts === +export type { A as AA } from "./a"; +>A : any +>AA : import("tests/cases/conformance/externalModules/typeOnly/a").A + +export type { B as BB } from "./b"; +>B : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B +>BB : import("tests/cases/conformance/externalModules/typeOnly/b").B + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import { AA, BB } from "./d"; +>AA : any +>BB : typeof BB + +=== tests/cases/conformance/externalModules/typeOnly/e.fixed.ts === +import type { AA, BB } from "./d"; +>AA : AA +>BB : BB + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type { A } from "./a"; +>A : A + +import type { B } from "./b"; +>B : B + +export { A, B as BB }; +>A : any +>B : typeof B +>BB : typeof B + +=== tests/cases/conformance/externalModules/typeOnly/f.fixed.ts === +import type { A } from "./a"; +>A : A + +import type { B } from "./b"; +>B : B + +export type { A, B as BB }; +>A : A +>B : typeof B +>BB : B + diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).errors.txt b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).errors.txt new file mode 100644 index 0000000000000..9823c1d1ae459 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).errors.txt @@ -0,0 +1,74 @@ +tests/cases/conformance/externalModules/typeOnly/c.ts(1,8): error TS1444: 'DefaultA' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/c.ts(2,10): error TS1444: 'A' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/c.ts(3,8): error TS1446: 'DefaultB' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/c.ts(4,10): error TS1446: 'B' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/d.ts(1,10): error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. +tests/cases/conformance/externalModules/typeOnly/d.ts(2,10): error TS1448: 'B' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled. +tests/cases/conformance/externalModules/typeOnly/e.ts(1,10): error TS1444: 'AA' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +tests/cases/conformance/externalModules/typeOnly/e.ts(1,14): error TS1446: 'BB' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. + + +==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ==== + export type A = {}; + export type { A as default }; + +==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ==== + class B {}; + export type { B, B as default }; + +==== tests/cases/conformance/externalModules/typeOnly/c.ts (4 errors) ==== + import DefaultA from "./a"; + ~~~~~~~~ +!!! error TS1444: 'DefaultA' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. + import { A } from "./a"; + ~ +!!! error TS1444: 'A' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. + import DefaultB from "./b"; + ~~~~~~~~ +!!! error TS1446: 'DefaultB' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:2:18: 'DefaultB' was exported here. + import { B } from "./b"; + ~ +!!! error TS1446: 'B' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:2:15: 'B' was exported here. + +==== tests/cases/conformance/externalModules/typeOnly/c.fixed.ts (0 errors) ==== + import type DefaultA from "./a"; + import type { A } from "./a"; + import type DefaultB from "./b"; + import type { B } from "./b"; + +==== tests/cases/conformance/externalModules/typeOnly/d.ts (2 errors) ==== + export { A as AA } from "./a"; + ~~~~~~~ +!!! error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. + export { B as BB } from "./b"; + ~~~~~~~ +!!! error TS1448: 'B' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:2:15: 'B' was exported here. + +==== tests/cases/conformance/externalModules/typeOnly/d.fixed.ts (0 errors) ==== + export type { A as AA } from "./a"; + export type { B as BB } from "./b"; + +==== tests/cases/conformance/externalModules/typeOnly/e.ts (2 errors) ==== + import { AA, BB } from "./d"; + ~~ +!!! error TS1444: 'AA' is a type and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. + ~~ +!!! error TS1446: 'BB' resolves to a type-only declaration and must be imported using a type-only import when 'preserveValueImports' and 'isolatedModules' are both enabled. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:2:15: 'BB' was exported here. + +==== tests/cases/conformance/externalModules/typeOnly/e.fixed.ts (0 errors) ==== + import type { AA, BB } from "./d"; + +==== tests/cases/conformance/externalModules/typeOnly/f.ts (0 errors) ==== + import type { A } from "./a"; + import type { B } from "./b"; + export { A, B as BB }; + +==== tests/cases/conformance/externalModules/typeOnly/f.fixed.ts (0 errors) ==== + import type { A } from "./a"; + import type { B } from "./b"; + export type { A, B as BB }; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).js b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).js new file mode 100644 index 0000000000000..36507e663afc9 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).js @@ -0,0 +1,73 @@ +//// [tests/cases/conformance/externalModules/typeOnly/preserveValueImports_errors.ts] //// + +//// [a.ts] +export type A = {}; +export type { A as default }; + +//// [b.ts] +class B {}; +export type { B, B as default }; + +//// [c.ts] +import DefaultA from "./a"; +import { A } from "./a"; +import DefaultB from "./b"; +import { B } from "./b"; + +//// [c.fixed.ts] +import type DefaultA from "./a"; +import type { A } from "./a"; +import type DefaultB from "./b"; +import type { B } from "./b"; + +//// [d.ts] +export { A as AA } from "./a"; +export { B as BB } from "./b"; + +//// [d.fixed.ts] +export type { A as AA } from "./a"; +export type { B as BB } from "./b"; + +//// [e.ts] +import { AA, BB } from "./d"; + +//// [e.fixed.ts] +import type { AA, BB } from "./d"; + +//// [f.ts] +import type { A } from "./a"; +import type { B } from "./b"; +export { A, B as BB }; + +//// [f.fixed.ts] +import type { A } from "./a"; +import type { B } from "./b"; +export type { A, B as BB }; + + +//// [a.js] +export {}; +//// [b.js] +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +; +export {}; +//// [c.js] +export {}; +//// [c.fixed.js] +export {}; +//// [d.js] +export {}; +//// [d.fixed.js] +export {}; +//// [e.js] +export {}; +//// [e.fixed.js] +export {}; +//// [f.js] +export {}; +//// [f.fixed.js] +export {}; diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).symbols b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).symbols new file mode 100644 index 0000000000000..0dd64238caf2a --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).symbols @@ -0,0 +1,95 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export type A = {}; +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export type { A as default }; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>default : Symbol(default, Decl(a.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +class B {}; +>B : Symbol(B, Decl(b.ts, 0, 0)) + +export type { B, B as default }; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>B : Symbol(B, Decl(b.ts, 0, 0)) +>default : Symbol(default, Decl(b.ts, 1, 16)) + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import DefaultA from "./a"; +>DefaultA : Symbol(DefaultA, Decl(c.ts, 0, 6)) + +import { A } from "./a"; +>A : Symbol(A, Decl(c.ts, 1, 8)) + +import DefaultB from "./b"; +>DefaultB : Symbol(DefaultB, Decl(c.ts, 2, 6)) + +import { B } from "./b"; +>B : Symbol(B, Decl(c.ts, 3, 8)) + +=== tests/cases/conformance/externalModules/typeOnly/c.fixed.ts === +import type DefaultA from "./a"; +>DefaultA : Symbol(DefaultA, Decl(c.fixed.ts, 0, 6)) + +import type { A } from "./a"; +>A : Symbol(A, Decl(c.fixed.ts, 1, 13)) + +import type DefaultB from "./b"; +>DefaultB : Symbol(DefaultB, Decl(c.fixed.ts, 2, 6)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(c.fixed.ts, 3, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export { A as AA } from "./a"; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>AA : Symbol(AA, Decl(d.ts, 0, 8)) + +export { B as BB } from "./b"; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>BB : Symbol(BB, Decl(d.ts, 1, 8)) + +=== tests/cases/conformance/externalModules/typeOnly/d.fixed.ts === +export type { A as AA } from "./a"; +>A : Symbol(A, Decl(a.ts, 0, 0)) +>AA : Symbol(AA, Decl(d.fixed.ts, 0, 13)) + +export type { B as BB } from "./b"; +>B : Symbol(B, Decl(b.ts, 1, 13)) +>BB : Symbol(BB, Decl(d.fixed.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import { AA, BB } from "./d"; +>AA : Symbol(AA, Decl(e.ts, 0, 8)) +>BB : Symbol(BB, Decl(e.ts, 0, 12)) + +=== tests/cases/conformance/externalModules/typeOnly/e.fixed.ts === +import type { AA, BB } from "./d"; +>AA : Symbol(AA, Decl(e.fixed.ts, 0, 13)) +>BB : Symbol(BB, Decl(e.fixed.ts, 0, 17)) + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type { A } from "./a"; +>A : Symbol(A, Decl(f.ts, 0, 13)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(f.ts, 1, 13)) + +export { A, B as BB }; +>A : Symbol(A, Decl(f.ts, 2, 8)) +>B : Symbol(B, Decl(f.ts, 1, 13)) +>BB : Symbol(BB, Decl(f.ts, 2, 11)) + +=== tests/cases/conformance/externalModules/typeOnly/f.fixed.ts === +import type { A } from "./a"; +>A : Symbol(A, Decl(f.fixed.ts, 0, 13)) + +import type { B } from "./b"; +>B : Symbol(B, Decl(f.fixed.ts, 1, 13)) + +export type { A, B as BB }; +>A : Symbol(A, Decl(f.fixed.ts, 2, 13)) +>B : Symbol(B, Decl(f.fixed.ts, 1, 13)) +>BB : Symbol(BB, Decl(f.fixed.ts, 2, 16)) + diff --git a/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).types b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).types new file mode 100644 index 0000000000000..1e8a912ed7ced --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_errors(isolatedmodules=true).types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.ts === +export type A = {}; +>A : A + +export type { A as default }; +>A : any +>default : A + +=== tests/cases/conformance/externalModules/typeOnly/b.ts === +class B {}; +>B : B + +export type { B, B as default }; +>B : B +>B : typeof B +>default : B + +=== tests/cases/conformance/externalModules/typeOnly/c.ts === +import DefaultA from "./a"; +>DefaultA : any + +import { A } from "./a"; +>A : any + +import DefaultB from "./b"; +>DefaultB : typeof DefaultB + +import { B } from "./b"; +>B : typeof DefaultB + +=== tests/cases/conformance/externalModules/typeOnly/c.fixed.ts === +import type DefaultA from "./a"; +>DefaultA : DefaultA + +import type { A } from "./a"; +>A : DefaultA + +import type DefaultB from "./b"; +>DefaultB : DefaultB + +import type { B } from "./b"; +>B : DefaultB + +=== tests/cases/conformance/externalModules/typeOnly/d.ts === +export { A as AA } from "./a"; +>A : any +>AA : any + +export { B as BB } from "./b"; +>B : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B +>BB : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B + +=== tests/cases/conformance/externalModules/typeOnly/d.fixed.ts === +export type { A as AA } from "./a"; +>A : any +>AA : import("tests/cases/conformance/externalModules/typeOnly/a").A + +export type { B as BB } from "./b"; +>B : typeof import("tests/cases/conformance/externalModules/typeOnly/b").B +>BB : import("tests/cases/conformance/externalModules/typeOnly/b").B + +=== tests/cases/conformance/externalModules/typeOnly/e.ts === +import { AA, BB } from "./d"; +>AA : any +>BB : typeof BB + +=== tests/cases/conformance/externalModules/typeOnly/e.fixed.ts === +import type { AA, BB } from "./d"; +>AA : AA +>BB : BB + +=== tests/cases/conformance/externalModules/typeOnly/f.ts === +import type { A } from "./a"; +>A : A + +import type { B } from "./b"; +>B : B + +export { A, B as BB }; +>A : any +>B : typeof B +>BB : typeof B + +=== tests/cases/conformance/externalModules/typeOnly/f.fixed.ts === +import type { A } from "./a"; +>A : A + +import type { B } from "./b"; +>B : B + +export type { A, B as BB }; +>A : A +>B : typeof B +>BB : B + diff --git a/tests/baselines/reference/preserveValueImports_module(module=amd).errors.txt b/tests/baselines/reference/preserveValueImports_module(module=amd).errors.txt new file mode 100644 index 0000000000000..204342959ca1b --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=amd).errors.txt @@ -0,0 +1,7 @@ +error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. + + +!!! error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. +==== tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports_module(module=amd).js b/tests/baselines/reference/preserveValueImports_module(module=amd).js new file mode 100644 index 0000000000000..f51632425da99 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=amd).js @@ -0,0 +1,9 @@ +//// [preserveValueImports_module.ts] +export {}; + + +//// [preserveValueImports_module.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.__esModule = true; +}); diff --git a/tests/baselines/reference/preserveValueImports_module(module=commonjs).errors.txt b/tests/baselines/reference/preserveValueImports_module(module=commonjs).errors.txt new file mode 100644 index 0000000000000..204342959ca1b --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=commonjs).errors.txt @@ -0,0 +1,7 @@ +error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. + + +!!! error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. +==== tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports_module(module=commonjs).js b/tests/baselines/reference/preserveValueImports_module(module=commonjs).js new file mode 100644 index 0000000000000..790566516ac13 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=commonjs).js @@ -0,0 +1,7 @@ +//// [preserveValueImports_module.ts] +export {}; + + +//// [preserveValueImports_module.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/preserveValueImports_module(module=es2015).js b/tests/baselines/reference/preserveValueImports_module(module=es2015).js new file mode 100644 index 0000000000000..c01c03cf616b8 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=es2015).js @@ -0,0 +1,6 @@ +//// [preserveValueImports_module.ts] +export {}; + + +//// [preserveValueImports_module.js] +export {}; diff --git a/tests/baselines/reference/preserveValueImports_module(module=system).errors.txt b/tests/baselines/reference/preserveValueImports_module(module=system).errors.txt new file mode 100644 index 0000000000000..204342959ca1b --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=system).errors.txt @@ -0,0 +1,7 @@ +error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. + + +!!! error TS5095: Option 'preserveValueImports' can only be used when 'module' is set to 'es2015' or later. +==== tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts (0 errors) ==== + export {}; + \ No newline at end of file diff --git a/tests/baselines/reference/preserveValueImports_module(module=system).js b/tests/baselines/reference/preserveValueImports_module(module=system).js new file mode 100644 index 0000000000000..f8d108572f495 --- /dev/null +++ b/tests/baselines/reference/preserveValueImports_module(module=system).js @@ -0,0 +1,14 @@ +//// [preserveValueImports_module.ts] +export {}; + + +//// [preserveValueImports_module.js] +System.register([], function (exports_1, context_1) { + "use strict"; + var __moduleName = context_1 && context_1.id; + return { + setters: [], + execute: function () { + } + }; +}); diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/preserveValueImports/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/preserveValueImports/tsconfig.json new file mode 100644 index 0000000000000..2c37ccb9b5c70 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/preserveValueImports/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "preserveValueImports": true + } +} diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 83b5f57342d38..96b9d1be78cd4 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index 2be01ddc5185f..9c26f5a029727 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ "declarationDir": "lib", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 01694c43ef3ac..a75d5adbedb87 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 14e6941541985..9f8f66fa059c2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 4c6956b782331..8d75086de68ea 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index 22622f8c57448..f66c53cd98f16 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 83b5f57342d38..96b9d1be78cd4 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 9d936c92387a3..85c5394078dc6 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 098547e332c28..763d33c30bb04 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -64,6 +64,7 @@ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index 818d097a27126..ed84c9e43922b 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ "declarationDir": "decls", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index a24e27e79b324..109062bb84503 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ "declarationDir": "decls", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index 5854bd52724b4..4255c9ffedd7f 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index 5273f50ea2f7f..2e6117272664a 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index 79033fbaea3ec..28924e1e61c1d 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index 2ad1060ce704f..20fd0c695b90d 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -85,6 +85,7 @@ interface Array { length: number; [n: number]: T; } // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ diff --git a/tests/cases/compiler/isolatedModulesReExportType.ts b/tests/cases/compiler/isolatedModulesReExportType.ts index 6d82fd3f180d1..8bb10bbf22931 100644 --- a/tests/cases/compiler/isolatedModulesReExportType.ts +++ b/tests/cases/compiler/isolatedModulesReExportType.ts @@ -21,6 +21,9 @@ declare module "baz" { export { T } from "foo"; // Also allowed. } +// @Filename: /reExportValueAsTypeOnly.ts +export type { C } from "./exportValue"; + // @Filename: /user.ts // Error, can't re-export something that's only a type. export { T } from "./exportT"; @@ -39,3 +42,11 @@ export type T3 = T; // Error, not clear (to an isolated module) whether `T4` is a type. import { T } from "./exportT"; export { T as T4 }; + +// Ok, type-only import indicates that the export can be elided. +import type { T as TT } from "./exportT"; +export { TT }; + +// Error, type-only declaration is in a different file. +import { C as CC } from "./reExportValueAsTypeOnly"; +export { CC }; diff --git a/tests/cases/conformance/externalModules/typeOnly/preserveValueImports.ts b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports.ts new file mode 100644 index 0000000000000..66326cb98bda4 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports.ts @@ -0,0 +1,28 @@ +// @preserveValueImports: true +// @isolatedModules: true,false +// @module: esnext + +// @Filename: a.ts +export default {}; +export const b = 0; +export const c = 1; +export interface D {} + +// @Filename: b.ts +import a, { b, c, D } from "./a"; + +// @Filename: c.ts +import * as a from "./a"; + +// @Filename: d.ts +export = {}; + +// @Filename: e.ts +import D = require("./d"); +import DD = require("./d"); +DD; + +// @Filename: f.ts +import type a from "./a"; +import { b, c } from "./a"; +b; diff --git a/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_errors.ts b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_errors.ts new file mode 100644 index 0000000000000..fc2a3612e7f75 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_errors.ts @@ -0,0 +1,47 @@ +// @preserveValueImports: true +// @isolatedModules: true,false +// @module: esnext + +// @Filename: a.ts +export type A = {}; +export type { A as default }; + +// @Filename: b.ts +class B {}; +export type { B, B as default }; + +// @Filename: c.ts +import DefaultA from "./a"; +import { A } from "./a"; +import DefaultB from "./b"; +import { B } from "./b"; + +// @Filename: c.fixed.ts +import type DefaultA from "./a"; +import type { A } from "./a"; +import type DefaultB from "./b"; +import type { B } from "./b"; + +// @Filename: d.ts +export { A as AA } from "./a"; +export { B as BB } from "./b"; + +// @Filename: d.fixed.ts +export type { A as AA } from "./a"; +export type { B as BB } from "./b"; + +// @Filename: e.ts +import { AA, BB } from "./d"; + +// @Filename: e.fixed.ts +import type { AA, BB } from "./d"; + +// @Filename: f.ts +import type { A } from "./a"; +import type { B } from "./b"; +export { A, B as BB }; + +// @Filename: f.fixed.ts +import type { A } from "./a"; +import type { B } from "./b"; +export type { A, B as BB }; diff --git a/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts new file mode 100644 index 0000000000000..27f78f707c5db --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/preserveValueImports_module.ts @@ -0,0 +1,4 @@ +// @preserveValueImports: true +// @module: amd,system,commonjs,es2015 +// @noTypesAndSymbols: true +export {};