From ddae38d449d74ec03f2dc764c93b88b277fdbd76 Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 14:32:51 -0800 Subject: [PATCH 1/8] Support `export type * from "mod"` --- src/compiler/checker.ts | 78 +++++++++++++---- src/compiler/diagnosticMessages.json | 4 - src/compiler/types.ts | 4 + src/compiler/utilitiesPublic.ts | 3 + .../reference/exportNamespace4.errors.txt | 16 ++-- tests/baselines/reference/exportNamespace4.js | 3 +- .../reference/exportNamespace5.errors.txt | 34 ++++++++ tests/baselines/reference/exportNamespace5.js | 87 +++++++++++++++++++ .../reference/exportNamespace5.symbols | 63 ++++++++++++++ .../reference/exportNamespace5.types | 63 ++++++++++++++ .../reference/exportNamespace6.errors.txt | 24 +++++ tests/baselines/reference/exportNamespace6.js | 59 +++++++++++++ .../reference/exportNamespace6.symbols | 30 +++++++ .../reference/exportNamespace6.types | 30 +++++++ .../reference/exportNamespace7.errors.txt | 46 ++++++++++ tests/baselines/reference/exportNamespace7.js | 75 ++++++++++++++++ .../reference/exportNamespace7.symbols | 61 +++++++++++++ .../reference/exportNamespace7.types | 61 +++++++++++++ .../reference/exportNamespace8.errors.txt | 27 ++++++ tests/baselines/reference/exportNamespace8.js | 78 +++++++++++++++++ .../reference/exportNamespace8.symbols | 40 +++++++++ .../reference/exportNamespace8.types | 40 +++++++++ .../reference/exportNamespace9.errors.txt | 36 ++++++++ tests/baselines/reference/exportNamespace9.js | 76 ++++++++++++++++ .../reference/exportNamespace9.symbols | 49 +++++++++++ .../reference/exportNamespace9.types | 49 +++++++++++ .../typeOnly/exportNamespace5.ts | 24 +++++ .../typeOnly/exportNamespace6.ts | 14 +++ .../typeOnly/exportNamespace7.ts | 23 +++++ .../typeOnly/exportNamespace8.ts | 17 ++++ .../typeOnly/exportNamespace9.ts | 27 ++++++ 31 files changed, 1207 insertions(+), 34 deletions(-) create mode 100644 tests/baselines/reference/exportNamespace5.errors.txt create mode 100644 tests/baselines/reference/exportNamespace5.js create mode 100644 tests/baselines/reference/exportNamespace5.symbols create mode 100644 tests/baselines/reference/exportNamespace5.types create mode 100644 tests/baselines/reference/exportNamespace6.errors.txt create mode 100644 tests/baselines/reference/exportNamespace6.js create mode 100644 tests/baselines/reference/exportNamespace6.symbols create mode 100644 tests/baselines/reference/exportNamespace6.types create mode 100644 tests/baselines/reference/exportNamespace7.errors.txt create mode 100644 tests/baselines/reference/exportNamespace7.js create mode 100644 tests/baselines/reference/exportNamespace7.symbols create mode 100644 tests/baselines/reference/exportNamespace7.types create mode 100644 tests/baselines/reference/exportNamespace8.errors.txt create mode 100644 tests/baselines/reference/exportNamespace8.js create mode 100644 tests/baselines/reference/exportNamespace8.symbols create mode 100644 tests/baselines/reference/exportNamespace8.types create mode 100644 tests/baselines/reference/exportNamespace9.errors.txt create mode 100644 tests/baselines/reference/exportNamespace9.js create mode 100644 tests/baselines/reference/exportNamespace9.symbols create mode 100644 tests/baselines/reference/exportNamespace9.types create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace6.ts create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace7.ts create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace8.ts create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace9.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 234b9ef18c675..98310cf091163 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3386,7 +3386,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value); if (typeOnlyDeclaration) { - const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier + const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration ? 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 unescapedName = unescapeLeadingUnderscores(name); @@ -3407,7 +3407,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostic, createDiagnosticForNode( typeOnlyDeclaration, - typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here, + typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + ? Diagnostics._0_was_exported_here + : Diagnostics._0_was_imported_here, unescapedName)); } @@ -3804,7 +3806,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) { if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfDeclaration(node))!; - const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier; + const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration; const message = isExport ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type : Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type; @@ -3812,7 +3814,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here; - const name = unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); + // TODO: how to get name for export *? + const name = typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration ? "*" : unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); addRelatedInfo(error(node.moduleReference, message), createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)); } } @@ -4025,7 +4028,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.Module) { const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText); const resolved = resolveSymbol(exportSymbol, dontResolveAlias); - markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false); + const exportStarDeclaration = getSymbolLinks(symbol).typeOnlyExportStarMap?.get(name.escapedText); + markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false, exportStarDeclaration, name.escapedText); return resolved; } } @@ -4386,6 +4390,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { immediateTarget: Symbol | undefined, finalTarget: Symbol | undefined, overwriteEmpty: boolean, + exportStarDeclaration?: ExportDeclaration & { readonly isTypeOnly: true }, + exportStarName?: __String, ): boolean { if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false; @@ -4397,6 +4403,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { links.typeOnlyDeclaration = aliasDeclaration; return true; } + if (exportStarDeclaration) { + const links = getSymbolLinks(sourceSymbol); + links.typeOnlyDeclaration = exportStarDeclaration; + if (sourceSymbol.escapedName !== exportStarName) { + links.typeOnlyExportStarName = exportStarName; + } + return true; + } const links = getSymbolLinks(sourceSymbol); return markSymbolOfAliasDeclarationIfTypeOnlyWorker(links, immediateTarget, overwriteEmpty) @@ -4422,7 +4436,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.typeOnlyDeclaration || undefined; } if (links.typeOnlyDeclaration) { - return getAllSymbolFlags(resolveAlias(links.typeOnlyDeclaration.symbol)) & include ? links.typeOnlyDeclaration : undefined; + const resolved = links.typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + ? resolveSymbol(getExportsOfModule(links.typeOnlyDeclaration.symbol.parent!).get(links.typeOnlyExportStarName || symbol.escapedName))! + : resolveAlias(links.typeOnlyDeclaration.symbol); + return getAllSymbolFlags(resolved) & include ? links.typeOnlyDeclaration : undefined; } return undefined; } @@ -5133,7 +5150,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getExportsOfModule(moduleSymbol: Symbol): SymbolTable { const links = getSymbolLinks(moduleSymbol); - return links.resolvedExports || (links.resolvedExports = getExportsOfModuleWorker(moduleSymbol)); + if (!links.resolvedExports) { + const { exports, typeOnlyExportStarMap } = getExportsOfModuleWorker(moduleSymbol); + links.resolvedExports = exports; + links.typeOnlyExportStarMap = typeOnlyExportStarMap; + } + return links.resolvedExports; } interface ExportCollisionTracker { @@ -5173,21 +5195,38 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); } - function getExportsOfModuleWorker(moduleSymbol: Symbol): SymbolTable { + function getExportsOfModuleWorker(moduleSymbol: Symbol) { const visitedSymbols: Symbol[] = []; + let typeOnlyExportStarMap: UnderscoreEscapedMap<ExportDeclaration & { readonly isTypeOnly: true }> | undefined; + const nonTypeOnlyNames = new Set<__String>(); // A module defined by an 'export=' consists of one export that needs to be resolved moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); + const exports = visit(moduleSymbol) || emptySymbols; - return visit(moduleSymbol) || emptySymbols; + if (typeOnlyExportStarMap) { + nonTypeOnlyNames.forEach(name => typeOnlyExportStarMap!.delete(name)); + } + + return { + exports, + typeOnlyExportStarMap, + }; // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. - function visit(symbol: Symbol | undefined): SymbolTable | undefined { + function visit(symbol: Symbol | undefined, exportStar?: ExportDeclaration, isTypeOnly?: boolean): SymbolTable | undefined { + if (!isTypeOnly && symbol?.exports) { + // Add non-type-only names before checking if we've visited this module, + // because we might have visited it via an 'export type *', and visiting + // again with 'export *' will override the type-onlyness of its exports. + symbol.exports.forEach((_, name) => nonTypeOnlyNames.add(name)); + } if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) { return; } const symbols = new Map(symbol.exports); + // All export * declarations are collected in an __export symbol by the binder const exportStars = symbol.exports.get(InternalSymbolName.ExportStar); if (exportStars) { @@ -5196,7 +5235,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (exportStars.declarations) { for (const node of exportStars.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); - const exportedSymbols = visit(resolvedModule); + const exportedSymbols = visit(resolvedModule, node as ExportDeclaration, isTypeOnly || (node as ExportDeclaration).isTypeOnly); extendExportSymbols( nestedSymbols, exportedSymbols, @@ -5221,6 +5260,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); extendExportSymbols(symbols, nestedSymbols); } + if (exportStar?.isTypeOnly) { + typeOnlyExportStarMap ??= new Map(); + symbols.forEach((_, escapedName) => typeOnlyExportStarMap!.set( + escapedName, + exportStar as ExportDeclaration & { readonly isTypeOnly: true })); + } return symbols; } } @@ -12131,7 +12176,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!links[resolutionKind]) { const isStatic = resolutionKind === MembersOrExportsResolutionKind.resolvedExports; const earlySymbols = !isStatic ? symbol.members : - symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol) : + symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol).exports : symbol.exports; // In the event we recursively resolve the members/exports of the symbol, we @@ -42983,13 +43028,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkGrammarExportDeclaration(node: ExportDeclaration): boolean { - if (node.isTypeOnly) { - if (node.exportClause?.kind === SyntaxKind.NamedExports) { - return checkGrammarNamedImportsOrExports(node.exportClause); - } - else { - return grammarErrorOnNode(node, Diagnostics.Only_named_exports_may_use_export_type); - } + if (node.isTypeOnly && node.exportClause?.kind === SyntaxKind.NamedExports) { + return checkGrammarNamedImportsOrExports(node.exportClause); } return false; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a2d3387381009..d83e6564a94f2 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1196,10 +1196,6 @@ "category": "Error", "code": 1382 }, - "Only named exports may use 'export type'.": { - "category": "Error", - "code": 1383 - }, "Function type notation must be parenthesized when used in a union type.": { "category": "Error", "code": 1385 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 325e3c109bdbe..1b70520fed00a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3817,6 +3817,7 @@ export type TypeOnlyCompatibleAliasDeclaration = | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier + | ExportDeclaration ; export type TypeOnlyAliasDeclaration = @@ -3825,6 +3826,7 @@ export type TypeOnlyAliasDeclaration = | NamespaceImport & { readonly parent: ImportClause & { readonly isTypeOnly: true } } | ImportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true } } }) | ExportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } }) + | ExportDeclaration & { readonly isTypeOnly: true } // export * from "mod" ; /** @@ -5802,6 +5804,8 @@ export interface SymbolLinks { deferralParent?: Type; // Source union/intersection of a deferred type cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs + typeOnlyExportStarMap?: UnderscoreEscapedMap<ExportDeclaration & { readonly isTypeOnly: true }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration + typeOnlyExportStarName?: __String; // Set to the name of the symbol re-exported by an 'export type *' declaration, when different from the symbol name isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label accessibleChainCache?: Map<string, Symbol[] | undefined>; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 7bb784a3a57bd..c8444b805a81a 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -54,6 +54,7 @@ import { EnumDeclaration, every, ExportAssignment, + ExportDeclaration, ExportSpecifier, Expression, FileReference, @@ -1458,6 +1459,8 @@ export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnl case SyntaxKind.ImportClause: case SyntaxKind.ImportEqualsDeclaration: return (node as ImportClause | ImportEqualsDeclaration).isTypeOnly; + case SyntaxKind.ExportDeclaration: + return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier && !(node as ExportDeclaration).exportClause; default: return false; } diff --git a/tests/baselines/reference/exportNamespace4.errors.txt b/tests/baselines/reference/exportNamespace4.errors.txt index 30b849456e67f..198589903ffed 100644 --- a/tests/baselines/reference/exportNamespace4.errors.txt +++ b/tests/baselines/reference/exportNamespace4.errors.txt @@ -1,23 +1,21 @@ -tests/cases/conformance/externalModules/typeOnly/b.ts(1,1): error TS1383: Only named exports may use 'export type'. -tests/cases/conformance/externalModules/typeOnly/c.ts(1,1): error TS1383: Only named exports may use 'export type'. +tests/cases/conformance/externalModules/typeOnly/d.ts(2,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. ==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ==== export class A {} -==== tests/cases/conformance/externalModules/typeOnly/b.ts (1 errors) ==== +==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ==== export type * from './a'; // Grammar error - ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1383: Only named exports may use 'export type'. -==== tests/cases/conformance/externalModules/typeOnly/c.ts (1 errors) ==== +==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ==== export type * as ns from './a'; // Grammar error - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS1383: Only named exports may use 'export type'. -==== tests/cases/conformance/externalModules/typeOnly/d.ts (0 errors) ==== +==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ==== import { A } from './b'; A; + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:1:1: 'A' was exported here. ==== tests/cases/conformance/externalModules/typeOnly/e.ts (0 errors) ==== import { ns } from './c'; diff --git a/tests/baselines/reference/exportNamespace4.js b/tests/baselines/reference/exportNamespace4.js index afab2c5f82b39..31e2d8442d07a 100644 --- a/tests/baselines/reference/exportNamespace4.js +++ b/tests/baselines/reference/exportNamespace4.js @@ -37,8 +37,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); //// [d.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var b_1 = require("./b"); -b_1.A; +A; //// [e.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/tests/baselines/reference/exportNamespace5.errors.txt b/tests/baselines/reference/exportNamespace5.errors.txt new file mode 100644 index 0000000000000..d94580faeeba7 --- /dev/null +++ b/tests/baselines/reference/exportNamespace5.errors.txt @@ -0,0 +1,34 @@ +/c.ts(2,16): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +/c.ts(3,17): error TS1362: 'C' cannot be used as a value because it was exported using 'export type'. + + +==== /a.ts (0 errors) ==== + export class A {} + export class B {} + export class X {} + +==== /b.ts (0 errors) ==== + export type * from "./a"; + export { X } from "./a"; + +==== /c.ts (2 errors) ==== + import { A, B as C, X } from "./b"; + let _: A = new A(); // Error + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'A' was exported here. + let __: C = new C(); // Error + ~ +!!! error TS1362: 'C' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'C' was exported here. + let ___: X = new X(); // Ok + +==== /d.ts (0 errors) ==== + export type * from "./a"; + export * from "./a"; + +==== /e.ts (0 errors) ==== + import { A, B, X } from "./d"; + let _: A = new A(); // Ok + let __: B = new B(); // Ok + let ___: X = new X(); // Ok \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace5.js b/tests/baselines/reference/exportNamespace5.js new file mode 100644 index 0000000000000..ae61f9da7236d --- /dev/null +++ b/tests/baselines/reference/exportNamespace5.js @@ -0,0 +1,87 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts] //// + +//// [a.ts] +export class A {} +export class B {} +export class X {} + +//// [b.ts] +export type * from "./a"; +export { X } from "./a"; + +//// [c.ts] +import { A, B as C, X } from "./b"; +let _: A = new A(); // Error +let __: C = new C(); // Error +let ___: X = new X(); // Ok + +//// [d.ts] +export type * from "./a"; +export * from "./a"; + +//// [e.ts] +import { A, B, X } from "./d"; +let _: A = new A(); // Ok +let __: B = new B(); // Ok +let ___: X = new X(); // Ok + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X = exports.B = exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +var X = /** @class */ (function () { + function X() { + } + return X; +}()); +exports.X = X; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X = void 0; +var a_1 = require("./a"); +Object.defineProperty(exports, "X", { enumerable: true, get: function () { return a_1.X; } }); +//// [c.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var b_1 = require("./b"); +var _ = new A(); // Error +var __ = new C(); // Error +var ___ = new b_1.X(); // Ok +//// [d.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./a"), exports); +//// [e.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var d_1 = require("./d"); +var _ = new d_1.A(); // Ok +var __ = new d_1.B(); // Ok +var ___ = new d_1.X(); // Ok diff --git a/tests/baselines/reference/exportNamespace5.symbols b/tests/baselines/reference/exportNamespace5.symbols new file mode 100644 index 0000000000000..da935da205c55 --- /dev/null +++ b/tests/baselines/reference/exportNamespace5.symbols @@ -0,0 +1,63 @@ +=== /a.ts === +export class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export class B {} +>B : Symbol(B, Decl(a.ts, 0, 17)) + +export class X {} +>X : Symbol(X, Decl(a.ts, 1, 17)) + +=== /b.ts === +export type * from "./a"; +export { X } from "./a"; +>X : Symbol(X, Decl(b.ts, 1, 8)) + +=== /c.ts === +import { A, B as C, X } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8)) +>B : Symbol(C, Decl(a.ts, 0, 17)) +>C : Symbol(C, Decl(c.ts, 0, 11)) +>X : Symbol(X, Decl(c.ts, 0, 19)) + +let _: A = new A(); // Error +>_ : Symbol(_, Decl(c.ts, 1, 3)) +>A : Symbol(A, Decl(c.ts, 0, 8)) +>A : Symbol(A, Decl(c.ts, 0, 8)) + +let __: C = new C(); // Error +>__ : Symbol(__, Decl(c.ts, 2, 3)) +>C : Symbol(C, Decl(c.ts, 0, 11)) +>C : Symbol(C, Decl(c.ts, 0, 11)) + +let ___: X = new X(); // Ok +>___ : Symbol(___, Decl(c.ts, 3, 3)) +>X : Symbol(X, Decl(c.ts, 0, 19)) +>X : Symbol(X, Decl(c.ts, 0, 19)) + +=== /d.ts === + +export type * from "./a"; +export * from "./a"; + +=== /e.ts === +import { A, B, X } from "./d"; +>A : Symbol(A, Decl(e.ts, 0, 8)) +>B : Symbol(B, Decl(e.ts, 0, 11)) +>X : Symbol(X, Decl(e.ts, 0, 14)) + +let _: A = new A(); // Ok +>_ : Symbol(_, Decl(e.ts, 1, 3)) +>A : Symbol(A, Decl(e.ts, 0, 8)) +>A : Symbol(A, Decl(e.ts, 0, 8)) + +let __: B = new B(); // Ok +>__ : Symbol(__, Decl(e.ts, 2, 3)) +>B : Symbol(B, Decl(e.ts, 0, 11)) +>B : Symbol(B, Decl(e.ts, 0, 11)) + +let ___: X = new X(); // Ok +>___ : Symbol(___, Decl(e.ts, 3, 3)) +>X : Symbol(X, Decl(e.ts, 0, 14)) +>X : Symbol(X, Decl(e.ts, 0, 14)) + diff --git a/tests/baselines/reference/exportNamespace5.types b/tests/baselines/reference/exportNamespace5.types new file mode 100644 index 0000000000000..59fdeb762b0e2 --- /dev/null +++ b/tests/baselines/reference/exportNamespace5.types @@ -0,0 +1,63 @@ +=== /a.ts === +export class A {} +>A : A + +export class B {} +>B : B + +export class X {} +>X : X + +=== /b.ts === +export type * from "./a"; +export { X } from "./a"; +>X : typeof import("/a").X + +=== /c.ts === +import { A, B as C, X } from "./b"; +>A : typeof A +>B : typeof C +>C : typeof C +>X : typeof X + +let _: A = new A(); // Error +>_ : A +>new A() : A +>A : typeof A + +let __: C = new C(); // Error +>__ : C +>new C() : C +>C : typeof C + +let ___: X = new X(); // Ok +>___ : X +>new X() : X +>X : typeof X + +=== /d.ts === + +export type * from "./a"; +export * from "./a"; + +=== /e.ts === +import { A, B, X } from "./d"; +>A : typeof A +>B : typeof B +>X : typeof X + +let _: A = new A(); // Ok +>_ : A +>new A() : A +>A : typeof A + +let __: B = new B(); // Ok +>__ : B +>new B() : B +>B : typeof B + +let ___: X = new X(); // Ok +>___ : X +>new X() : X +>X : typeof X + diff --git a/tests/baselines/reference/exportNamespace6.errors.txt b/tests/baselines/reference/exportNamespace6.errors.txt new file mode 100644 index 0000000000000..b639df1663561 --- /dev/null +++ b/tests/baselines/reference/exportNamespace6.errors.txt @@ -0,0 +1,24 @@ +/d.ts(2,16): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +/d.ts(3,17): error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. + + +==== /a.ts (0 errors) ==== + export class A {} + export class B {} + +==== /b.ts (0 errors) ==== + export type * from "./a"; + +==== /c.ts (0 errors) ==== + export * from "./b"; + +==== /d.ts (2 errors) ==== + import { A, B } from "./c"; + let _: A = new A(); // Error + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'A' was exported here. + let __: B = new B(); // Error + ~ +!!! error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'B' was exported here. \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace6.js b/tests/baselines/reference/exportNamespace6.js new file mode 100644 index 0000000000000..bc9ca8bdb5da1 --- /dev/null +++ b/tests/baselines/reference/exportNamespace6.js @@ -0,0 +1,59 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace6.ts] //// + +//// [a.ts] +export class A {} +export class B {} + +//// [b.ts] +export type * from "./a"; + +//// [c.ts] +export * from "./b"; + +//// [d.ts] +import { A, B } from "./c"; +let _: A = new A(); // Error +let __: B = new B(); // Error + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [c.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./b"), exports); +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _ = new A(); // Error +var __ = new B(); // Error diff --git a/tests/baselines/reference/exportNamespace6.symbols b/tests/baselines/reference/exportNamespace6.symbols new file mode 100644 index 0000000000000..97f4e9cd4e09e --- /dev/null +++ b/tests/baselines/reference/exportNamespace6.symbols @@ -0,0 +1,30 @@ +=== /a.ts === +export class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export class B {} +>B : Symbol(B, Decl(a.ts, 0, 17)) + +=== /b.ts === + +export type * from "./a"; + +=== /c.ts === + +export * from "./b"; + +=== /d.ts === +import { A, B } from "./c"; +>A : Symbol(A, Decl(d.ts, 0, 8)) +>B : Symbol(B, Decl(d.ts, 0, 11)) + +let _: A = new A(); // Error +>_ : Symbol(_, Decl(d.ts, 1, 3)) +>A : Symbol(A, Decl(d.ts, 0, 8)) +>A : Symbol(A, Decl(d.ts, 0, 8)) + +let __: B = new B(); // Error +>__ : Symbol(__, Decl(d.ts, 2, 3)) +>B : Symbol(B, Decl(d.ts, 0, 11)) +>B : Symbol(B, Decl(d.ts, 0, 11)) + diff --git a/tests/baselines/reference/exportNamespace6.types b/tests/baselines/reference/exportNamespace6.types new file mode 100644 index 0000000000000..9b51612a2af64 --- /dev/null +++ b/tests/baselines/reference/exportNamespace6.types @@ -0,0 +1,30 @@ +=== /a.ts === +export class A {} +>A : A + +export class B {} +>B : B + +=== /b.ts === + +export type * from "./a"; + +=== /c.ts === + +export * from "./b"; + +=== /d.ts === +import { A, B } from "./c"; +>A : typeof A +>B : typeof B + +let _: A = new A(); // Error +>_ : A +>new A() : A +>A : typeof A + +let __: B = new B(); // Error +>__ : B +>new B() : B +>B : typeof B + diff --git a/tests/baselines/reference/exportNamespace7.errors.txt b/tests/baselines/reference/exportNamespace7.errors.txt new file mode 100644 index 0000000000000..c713c7ec4e12f --- /dev/null +++ b/tests/baselines/reference/exportNamespace7.errors.txt @@ -0,0 +1,46 @@ +/c.ts(2,16): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +/c.ts(3,17): error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. +/e.ts(2,16): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +/e.ts(3,17): error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. +/e.ts(4,18): error TS1362: 'C' cannot be used as a value because it was exported using 'export type'. + + +==== /a.ts (0 errors) ==== + export class A {} + export class B {} + export class C {} + +==== /b.ts (0 errors) ==== + export type * from "./a"; + export class C {} + +==== /c.ts (2 errors) ==== + import { A, B, C } from "./b"; + let _: A = new A(); // Error + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'A' was exported here. + let __: B = new B(); // Error + ~ +!!! error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:1: 'B' was exported here. + let ___: C = new C(); // Ok + +==== /d.ts (0 errors) ==== + export type * from "./b"; + +==== /e.ts (3 errors) ==== + import { A, B, C } from "./d"; + let _: A = new A(); // Error + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /d.ts:1:1: 'A' was exported here. + let __: B = new B(); // Error + ~ +!!! error TS1362: 'B' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /d.ts:1:1: 'B' was exported here. + let ___: C = new C(); // Error + ~ +!!! error TS1362: 'C' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /d.ts:1:1: 'C' was exported here. + \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace7.js b/tests/baselines/reference/exportNamespace7.js new file mode 100644 index 0000000000000..f1b1be12f1be1 --- /dev/null +++ b/tests/baselines/reference/exportNamespace7.js @@ -0,0 +1,75 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace7.ts] //// + +//// [a.ts] +export class A {} +export class B {} +export class C {} + +//// [b.ts] +export type * from "./a"; +export class C {} + +//// [c.ts] +import { A, B, C } from "./b"; +let _: A = new A(); // Error +let __: B = new B(); // Error +let ___: C = new C(); // Ok + +//// [d.ts] +export type * from "./b"; + +//// [e.ts] +import { A, B, C } from "./d"; +let _: A = new A(); // Error +let __: B = new B(); // Error +let ___: C = new C(); // Error + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.C = exports.B = exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +var C = /** @class */ (function () { + function C() { + } + return C; +}()); +exports.C = C; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.C = void 0; +var C = /** @class */ (function () { + function C() { + } + return C; +}()); +exports.C = C; +//// [c.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var b_1 = require("./b"); +var _ = new A(); // Error +var __ = new B(); // Error +var ___ = new b_1.C(); // Ok +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [e.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _ = new A(); // Error +var __ = new B(); // Error +var ___ = new C(); // Error diff --git a/tests/baselines/reference/exportNamespace7.symbols b/tests/baselines/reference/exportNamespace7.symbols new file mode 100644 index 0000000000000..3ed0c38720bbd --- /dev/null +++ b/tests/baselines/reference/exportNamespace7.symbols @@ -0,0 +1,61 @@ +=== /a.ts === +export class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export class B {} +>B : Symbol(B, Decl(a.ts, 0, 17)) + +export class C {} +>C : Symbol(C, Decl(a.ts, 1, 17)) + +=== /b.ts === +export type * from "./a"; +export class C {} +>C : Symbol(C, Decl(b.ts, 0, 25)) + +=== /c.ts === +import { A, B, C } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8)) +>B : Symbol(B, Decl(c.ts, 0, 11)) +>C : Symbol(C, Decl(c.ts, 0, 14)) + +let _: A = new A(); // Error +>_ : Symbol(_, Decl(c.ts, 1, 3)) +>A : Symbol(A, Decl(c.ts, 0, 8)) +>A : Symbol(A, Decl(c.ts, 0, 8)) + +let __: B = new B(); // Error +>__ : Symbol(__, Decl(c.ts, 2, 3)) +>B : Symbol(B, Decl(c.ts, 0, 11)) +>B : Symbol(B, Decl(c.ts, 0, 11)) + +let ___: C = new C(); // Ok +>___ : Symbol(___, Decl(c.ts, 3, 3)) +>C : Symbol(C, Decl(c.ts, 0, 14)) +>C : Symbol(C, Decl(c.ts, 0, 14)) + +=== /d.ts === + +export type * from "./b"; + +=== /e.ts === +import { A, B, C } from "./d"; +>A : Symbol(A, Decl(e.ts, 0, 8)) +>B : Symbol(B, Decl(e.ts, 0, 11)) +>C : Symbol(C, Decl(e.ts, 0, 14)) + +let _: A = new A(); // Error +>_ : Symbol(_, Decl(e.ts, 1, 3)) +>A : Symbol(A, Decl(e.ts, 0, 8)) +>A : Symbol(A, Decl(e.ts, 0, 8)) + +let __: B = new B(); // Error +>__ : Symbol(__, Decl(e.ts, 2, 3)) +>B : Symbol(B, Decl(e.ts, 0, 11)) +>B : Symbol(B, Decl(e.ts, 0, 11)) + +let ___: C = new C(); // Error +>___ : Symbol(___, Decl(e.ts, 3, 3)) +>C : Symbol(C, Decl(e.ts, 0, 14)) +>C : Symbol(C, Decl(e.ts, 0, 14)) + diff --git a/tests/baselines/reference/exportNamespace7.types b/tests/baselines/reference/exportNamespace7.types new file mode 100644 index 0000000000000..7ddebff0202cf --- /dev/null +++ b/tests/baselines/reference/exportNamespace7.types @@ -0,0 +1,61 @@ +=== /a.ts === +export class A {} +>A : A + +export class B {} +>B : B + +export class C {} +>C : C + +=== /b.ts === +export type * from "./a"; +export class C {} +>C : C + +=== /c.ts === +import { A, B, C } from "./b"; +>A : typeof A +>B : typeof B +>C : typeof C + +let _: A = new A(); // Error +>_ : A +>new A() : A +>A : typeof A + +let __: B = new B(); // Error +>__ : B +>new B() : B +>B : typeof B + +let ___: C = new C(); // Ok +>___ : C +>new C() : C +>C : typeof C + +=== /d.ts === + +export type * from "./b"; + +=== /e.ts === +import { A, B, C } from "./d"; +>A : typeof A +>B : typeof B +>C : typeof C + +let _: A = new A(); // Error +>_ : A +>new A() : A +>A : typeof A + +let __: B = new B(); // Error +>__ : B +>new B() : B +>B : typeof B + +let ___: C = new C(); // Error +>___ : C +>new C() : C +>C : typeof C + diff --git a/tests/baselines/reference/exportNamespace8.errors.txt b/tests/baselines/reference/exportNamespace8.errors.txt new file mode 100644 index 0000000000000..8ee301e187189 --- /dev/null +++ b/tests/baselines/reference/exportNamespace8.errors.txt @@ -0,0 +1,27 @@ +/c.ts(2,1): error TS2308: Module "./a" has already exported a member named 'B'. Consider explicitly re-exporting to resolve the ambiguity. +/d.ts(2,16): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. + + +==== /a.ts (0 errors) ==== + export class A {} + export class B {} + +==== /b.ts (0 errors) ==== + export class B {} + export class C {} + +==== /c.ts (1 errors) ==== + export type * from "./a"; + export * from "./b"; // Collision error + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2308: Module "./a" has already exported a member named 'B'. Consider explicitly re-exporting to resolve the ambiguity. + +==== /d.ts (1 errors) ==== + import { A, B, C } from "./c"; + let _: A = new A(); // Error + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /c.ts:1:1: 'A' was exported here. + let __: B = new B(); // Ok + let ___: C = new C(); // Ok + \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace8.js b/tests/baselines/reference/exportNamespace8.js new file mode 100644 index 0000000000000..43747e6d03eed --- /dev/null +++ b/tests/baselines/reference/exportNamespace8.js @@ -0,0 +1,78 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace8.ts] //// + +//// [a.ts] +export class A {} +export class B {} + +//// [b.ts] +export class B {} +export class C {} + +//// [c.ts] +export type * from "./a"; +export * from "./b"; // Collision error + +//// [d.ts] +import { A, B, C } from "./c"; +let _: A = new A(); // Error +let __: B = new B(); // Ok +let ___: C = new C(); // Ok + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.C = exports.B = void 0; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +var C = /** @class */ (function () { + function C() { + } + return C; +}()); +exports.C = C; +//// [c.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./b"), exports); // Collision error +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var c_1 = require("./c"); +var _ = new A(); // Error +var __ = new c_1.B(); // Ok +var ___ = new c_1.C(); // Ok diff --git a/tests/baselines/reference/exportNamespace8.symbols b/tests/baselines/reference/exportNamespace8.symbols new file mode 100644 index 0000000000000..934ea38573b11 --- /dev/null +++ b/tests/baselines/reference/exportNamespace8.symbols @@ -0,0 +1,40 @@ +=== /a.ts === +export class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export class B {} +>B : Symbol(B, Decl(a.ts, 0, 17)) + +=== /b.ts === +export class B {} +>B : Symbol(B, Decl(b.ts, 0, 0)) + +export class C {} +>C : Symbol(C, Decl(b.ts, 0, 17)) + +=== /c.ts === + +export type * from "./a"; +export * from "./b"; // Collision error + +=== /d.ts === +import { A, B, C } from "./c"; +>A : Symbol(A, Decl(d.ts, 0, 8)) +>B : Symbol(B, Decl(d.ts, 0, 11)) +>C : Symbol(C, Decl(d.ts, 0, 14)) + +let _: A = new A(); // Error +>_ : Symbol(_, Decl(d.ts, 1, 3)) +>A : Symbol(A, Decl(d.ts, 0, 8)) +>A : Symbol(A, Decl(d.ts, 0, 8)) + +let __: B = new B(); // Ok +>__ : Symbol(__, Decl(d.ts, 2, 3)) +>B : Symbol(B, Decl(d.ts, 0, 11)) +>B : Symbol(B, Decl(d.ts, 0, 11)) + +let ___: C = new C(); // Ok +>___ : Symbol(___, Decl(d.ts, 3, 3)) +>C : Symbol(C, Decl(d.ts, 0, 14)) +>C : Symbol(C, Decl(d.ts, 0, 14)) + diff --git a/tests/baselines/reference/exportNamespace8.types b/tests/baselines/reference/exportNamespace8.types new file mode 100644 index 0000000000000..12b329db47542 --- /dev/null +++ b/tests/baselines/reference/exportNamespace8.types @@ -0,0 +1,40 @@ +=== /a.ts === +export class A {} +>A : A + +export class B {} +>B : B + +=== /b.ts === +export class B {} +>B : B + +export class C {} +>C : C + +=== /c.ts === + +export type * from "./a"; +export * from "./b"; // Collision error + +=== /d.ts === +import { A, B, C } from "./c"; +>A : typeof A +>B : typeof B +>C : typeof C + +let _: A = new A(); // Error +>_ : A +>new A() : A +>A : typeof A + +let __: B = new B(); // Ok +>__ : B +>new B() : B +>B : typeof B + +let ___: C = new C(); // Ok +>___ : C +>new C() : C +>C : typeof C + diff --git a/tests/baselines/reference/exportNamespace9.errors.txt b/tests/baselines/reference/exportNamespace9.errors.txt new file mode 100644 index 0000000000000..a7df9f03bd748 --- /dev/null +++ b/tests/baselines/reference/exportNamespace9.errors.txt @@ -0,0 +1,36 @@ +/f.ts(2,1): error TS2308: Module "./e" has already exported a member named 'A'. Consider explicitly re-exporting to resolve the ambiguity. +/g.ts(3,10): error TS2749: 'A' refers to a value, but is being used as a type here. Did you mean 'typeof A'? + + +==== /a.ts (0 errors) ==== + export type A = number; + +==== /b.ts (0 errors) ==== + export type * from "./a"; + +==== /c.ts (0 errors) ==== + import { A } from "./b"; + const A = 1; + export { A }; + +==== /d.ts (0 errors) ==== + import { A } from "./c"; + A; // Ok + type _ = A; + +==== /e.ts (0 errors) ==== + export const A = 1; + +==== /f.ts (1 errors) ==== + export * from "./e"; + export type * from "./a"; // Collision error + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2308: Module "./e" has already exported a member named 'A'. Consider explicitly re-exporting to resolve the ambiguity. + +==== /g.ts (1 errors) ==== + import { A } from "./f"; + A; + type _ = A; // Follow-on from collision error + ~ +!!! error TS2749: 'A' refers to a value, but is being used as a type here. Did you mean 'typeof A'? + \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace9.js b/tests/baselines/reference/exportNamespace9.js new file mode 100644 index 0000000000000..a0b5bb61edf5e --- /dev/null +++ b/tests/baselines/reference/exportNamespace9.js @@ -0,0 +1,76 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace9.ts] //// + +//// [a.ts] +export type A = number; + +//// [b.ts] +export type * from "./a"; + +//// [c.ts] +import { A } from "./b"; +const A = 1; +export { A }; + +//// [d.ts] +import { A } from "./c"; +A; // Ok +type _ = A; + +//// [e.ts] +export const A = 1; + +//// [f.ts] +export * from "./e"; +export type * from "./a"; // Collision error + +//// [g.ts] +import { A } from "./f"; +A; +type _ = A; // Follow-on from collision error + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [c.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; +var A = 1; +exports.A = A; +//// [d.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var c_1 = require("./c"); +c_1.A; // Ok +//// [e.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; +exports.A = 1; +//// [f.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./e"), exports); +//// [g.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var f_1 = require("./f"); +f_1.A; diff --git a/tests/baselines/reference/exportNamespace9.symbols b/tests/baselines/reference/exportNamespace9.symbols new file mode 100644 index 0000000000000..b0b81d8dce64d --- /dev/null +++ b/tests/baselines/reference/exportNamespace9.symbols @@ -0,0 +1,49 @@ +=== /a.ts === +export type A = number; +>A : Symbol(A, Decl(a.ts, 0, 0)) + +=== /b.ts === + +export type * from "./a"; + +=== /c.ts === +import { A } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 1, 5)) + +const A = 1; +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 1, 5)) + +export { A }; +>A : Symbol(A, Decl(c.ts, 2, 8)) + +=== /d.ts === +import { A } from "./c"; +>A : Symbol(A, Decl(d.ts, 0, 8)) + +A; // Ok +>A : Symbol(A, Decl(d.ts, 0, 8)) + +type _ = A; +>_ : Symbol(_, Decl(d.ts, 1, 2)) +>A : Symbol(A, Decl(d.ts, 0, 8)) + +=== /e.ts === +export const A = 1; +>A : Symbol(A, Decl(e.ts, 0, 12)) + +=== /f.ts === + +export * from "./e"; +export type * from "./a"; // Collision error + +=== /g.ts === +import { A } from "./f"; +>A : Symbol(A, Decl(g.ts, 0, 8)) + +A; +>A : Symbol(A, Decl(g.ts, 0, 8)) + +type _ = A; // Follow-on from collision error +>_ : Symbol(_, Decl(g.ts, 1, 2)) +>A : Symbol(A) + diff --git a/tests/baselines/reference/exportNamespace9.types b/tests/baselines/reference/exportNamespace9.types new file mode 100644 index 0000000000000..d5f1fa1bf3685 --- /dev/null +++ b/tests/baselines/reference/exportNamespace9.types @@ -0,0 +1,49 @@ +=== /a.ts === +export type A = number; +>A : number + +=== /b.ts === + +export type * from "./a"; + +=== /c.ts === +import { A } from "./b"; +>A : 1 + +const A = 1; +>A : 1 +>1 : 1 + +export { A }; +>A : 1 + +=== /d.ts === +import { A } from "./c"; +>A : 1 + +A; // Ok +>A : 1 + +type _ = A; +>_ : number + +=== /e.ts === +export const A = 1; +>A : 1 +>1 : 1 + +=== /f.ts === + +export * from "./e"; +export type * from "./a"; // Collision error + +=== /g.ts === +import { A } from "./f"; +>A : 1 + +A; +>A : 1 + +type _ = A; // Follow-on from collision error +>_ : A + diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts new file mode 100644 index 0000000000000..c085d6ced438c --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts @@ -0,0 +1,24 @@ +// @Filename: /a.ts +export class A {} +export class B {} +export class X {} + +// @Filename: /b.ts +export type * from "./a"; +export { X } from "./a"; + +// @Filename: /c.ts +import { A, B as C, X } from "./b"; +let _: A = new A(); // Error +let __: C = new C(); // Error +let ___: X = new X(); // Ok + +// @Filename: /d.ts +export type * from "./a"; +export * from "./a"; + +// @Filename: /e.ts +import { A, B, X } from "./d"; +let _: A = new A(); // Ok +let __: B = new B(); // Ok +let ___: X = new X(); // Ok \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace6.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace6.ts new file mode 100644 index 0000000000000..5574c8a7d1b68 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace6.ts @@ -0,0 +1,14 @@ +// @Filename: /a.ts +export class A {} +export class B {} + +// @Filename: /b.ts +export type * from "./a"; + +// @Filename: /c.ts +export * from "./b"; + +// @Filename: /d.ts +import { A, B } from "./c"; +let _: A = new A(); // Error +let __: B = new B(); // Error \ No newline at end of file diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace7.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace7.ts new file mode 100644 index 0000000000000..7fa5688497761 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace7.ts @@ -0,0 +1,23 @@ +// @Filename: /a.ts +export class A {} +export class B {} +export class C {} + +// @Filename: /b.ts +export type * from "./a"; +export class C {} + +// @Filename: /c.ts +import { A, B, C } from "./b"; +let _: A = new A(); // Error +let __: B = new B(); // Error +let ___: C = new C(); // Ok + +// @Filename: /d.ts +export type * from "./b"; + +// @Filename: /e.ts +import { A, B, C } from "./d"; +let _: A = new A(); // Error +let __: B = new B(); // Error +let ___: C = new C(); // Error diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace8.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace8.ts new file mode 100644 index 0000000000000..2fab2f62f2bcc --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace8.ts @@ -0,0 +1,17 @@ +// @Filename: /a.ts +export class A {} +export class B {} + +// @Filename: /b.ts +export class B {} +export class C {} + +// @Filename: /c.ts +export type * from "./a"; +export * from "./b"; // Collision error + +// @Filename: /d.ts +import { A, B, C } from "./c"; +let _: A = new A(); // Error +let __: B = new B(); // Ok +let ___: C = new C(); // Ok diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace9.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace9.ts new file mode 100644 index 0000000000000..b3693b8b86721 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace9.ts @@ -0,0 +1,27 @@ +// @Filename: /a.ts +export type A = number; + +// @Filename: /b.ts +export type * from "./a"; + +// @Filename: /c.ts +import { A } from "./b"; +const A = 1; +export { A }; + +// @Filename: /d.ts +import { A } from "./c"; +A; // Ok +type _ = A; + +// @Filename: /e.ts +export const A = 1; + +// @Filename: /f.ts +export * from "./e"; +export type * from "./a"; // Collision error + +// @Filename: /g.ts +import { A } from "./f"; +A; +type _ = A; // Follow-on from collision error From 23e4a1448a3ff6f9f2a47db377f94bf0f91a8ffb Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 14:43:34 -0800 Subject: [PATCH 2/8] Enable for namespace exports --- src/compiler/checker.ts | 4 +-- src/compiler/types.ts | 2 ++ src/compiler/utilitiesPublic.ts | 3 ++ .../reference/exportNamespace10.errors.txt | 15 ++++++++++ .../baselines/reference/exportNamespace10.js | 29 +++++++++++++++++++ .../reference/exportNamespace10.symbols | 20 +++++++++++++ .../reference/exportNamespace10.types | 20 +++++++++++++ .../typeOnly/exportNamespace10.ts | 9 ++++++ 8 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/exportNamespace10.errors.txt create mode 100644 tests/baselines/reference/exportNamespace10.js create mode 100644 tests/baselines/reference/exportNamespace10.symbols create mode 100644 tests/baselines/reference/exportNamespace10.types create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace10.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98310cf091163..b47ae45f0351f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3386,7 +3386,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value); if (typeOnlyDeclaration) { - const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport ? 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 unescapedName = unescapeLeadingUnderscores(name); @@ -3407,7 +3407,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { diagnostic, createDiagnosticForNode( typeOnlyDeclaration, - typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration + typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier || typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration || typeOnlyDeclaration.kind === SyntaxKind.NamespaceExport ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here, unescapedName)); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1b70520fed00a..b23552c87055e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3818,6 +3818,7 @@ export type TypeOnlyCompatibleAliasDeclaration = | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration + | NamespaceExport ; export type TypeOnlyAliasDeclaration = @@ -3827,6 +3828,7 @@ export type TypeOnlyAliasDeclaration = | ImportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true } } }) | ExportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } }) | ExportDeclaration & { readonly isTypeOnly: true } // export * from "mod" + | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } // export * as ns from "mod" ; /** diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index c8444b805a81a..a9509dfa9d17f 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -209,6 +209,7 @@ import { NamedExportBindings, NamedImportBindings, NamespaceBody, + NamespaceExport, NamespaceImport, NewExpression, Node, @@ -1461,6 +1462,8 @@ export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnl return (node as ImportClause | ImportEqualsDeclaration).isTypeOnly; case SyntaxKind.ExportDeclaration: return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier && !(node as ExportDeclaration).exportClause; + case SyntaxKind.NamespaceExport: + return (node as NamespaceExport).parent.isTypeOnly; default: return false; } diff --git a/tests/baselines/reference/exportNamespace10.errors.txt b/tests/baselines/reference/exportNamespace10.errors.txt new file mode 100644 index 0000000000000..662fd40c92d4c --- /dev/null +++ b/tests/baselines/reference/exportNamespace10.errors.txt @@ -0,0 +1,15 @@ +/c.ts(2,19): error TS1362: 'ns' cannot be used as a value because it was exported using 'export type'. + + +==== /a.ts (0 errors) ==== + export class A {} + +==== /b.ts (0 errors) ==== + export type * as ns from "./a"; + +==== /c.ts (1 errors) ==== + import { ns } from "./b"; + let _: ns.A = new ns.A(); // Error + ~~ +!!! error TS1362: 'ns' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 /b.ts:1:13: 'ns' was exported here. \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace10.js b/tests/baselines/reference/exportNamespace10.js new file mode 100644 index 0000000000000..4ed852f618bde --- /dev/null +++ b/tests/baselines/reference/exportNamespace10.js @@ -0,0 +1,29 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace10.ts] //// + +//// [a.ts] +export class A {} + +//// [b.ts] +export type * as ns from "./a"; + +//// [c.ts] +import { ns } from "./b"; +let _: ns.A = new ns.A(); // Error + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [c.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var _ = new ns.A(); // Error diff --git a/tests/baselines/reference/exportNamespace10.symbols b/tests/baselines/reference/exportNamespace10.symbols new file mode 100644 index 0000000000000..367d0222a89c4 --- /dev/null +++ b/tests/baselines/reference/exportNamespace10.symbols @@ -0,0 +1,20 @@ +=== /a.ts === +export class A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +=== /b.ts === +export type * as ns from "./a"; +>ns : Symbol(ns, Decl(b.ts, 0, 11)) + +=== /c.ts === +import { ns } from "./b"; +>ns : Symbol(ns, Decl(c.ts, 0, 8)) + +let _: ns.A = new ns.A(); // Error +>_ : Symbol(_, Decl(c.ts, 1, 3)) +>ns : Symbol(ns, Decl(c.ts, 0, 8)) +>A : Symbol(ns.A, Decl(a.ts, 0, 0)) +>ns.A : Symbol(ns.A, Decl(a.ts, 0, 0)) +>ns : Symbol(ns, Decl(c.ts, 0, 8)) +>A : Symbol(ns.A, Decl(a.ts, 0, 0)) + diff --git a/tests/baselines/reference/exportNamespace10.types b/tests/baselines/reference/exportNamespace10.types new file mode 100644 index 0000000000000..a9976401137f5 --- /dev/null +++ b/tests/baselines/reference/exportNamespace10.types @@ -0,0 +1,20 @@ +=== /a.ts === +export class A {} +>A : A + +=== /b.ts === +export type * as ns from "./a"; +>ns : typeof import("/a") + +=== /c.ts === +import { ns } from "./b"; +>ns : typeof ns + +let _: ns.A = new ns.A(); // Error +>_ : ns.A +>ns : any +>new ns.A() : ns.A +>ns.A : typeof ns.A +>ns : typeof ns +>A : typeof ns.A + diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace10.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace10.ts new file mode 100644 index 0000000000000..05a3baf824abc --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace10.ts @@ -0,0 +1,9 @@ +// @Filename: /a.ts +export class A {} + +// @Filename: /b.ts +export type * as ns from "./a"; + +// @Filename: /c.ts +import { ns } from "./b"; +let _: ns.A = new ns.A(); // Error \ No newline at end of file From 08701ac6e987987e30984bb040b097216a0a07bf Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 15:01:46 -0800 Subject: [PATCH 3/8] Clean up some types --- src/compiler/types.ts | 7 ++++++- src/compiler/utilitiesPublic.ts | 23 +++++++++++++++++------ src/services/completions.ts | 13 +++++++------ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b23552c87055e..04b41852ca6e9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3821,16 +3821,21 @@ export type TypeOnlyCompatibleAliasDeclaration = | NamespaceExport ; -export type TypeOnlyAliasDeclaration = +export type TypeOnlyImportDeclaration = | ImportClause & { readonly isTypeOnly: true, readonly name: Identifier } | ImportEqualsDeclaration & { readonly isTypeOnly: true } | NamespaceImport & { readonly parent: ImportClause & { readonly isTypeOnly: true } } | ImportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedImports & { readonly parent: ImportClause & { readonly isTypeOnly: true } } }) + ; + +export type TypeOnlyExportDeclaration = | ExportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } }) | ExportDeclaration & { readonly isTypeOnly: true } // export * from "mod" | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } // export * as ns from "mod" ; +export type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; + /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index a9509dfa9d17f..95703ddc11d2b 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -92,7 +92,6 @@ import { Identifier, ImportClause, ImportEqualsDeclaration, - ImportOrExportSpecifier, ImportSpecifier, ImportTypeNode, isAccessExpression, @@ -263,6 +262,8 @@ import { TypeElement, TypeNode, TypeOnlyAliasDeclaration, + TypeOnlyExportDeclaration, + TypeOnlyImportDeclaration, TypeParameterDeclaration, TypeReferenceType, UnaryExpression, @@ -1450,23 +1451,33 @@ export function isImportOrExportSpecifier(node: Node): node is ImportSpecifier | return isImportSpecifier(node) || isExportSpecifier(node); } -export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration { +export function isTypeOnlyImportDeclaration(node: Node): node is TypeOnlyImportDeclaration { switch (node.kind) { case SyntaxKind.ImportSpecifier: - case SyntaxKind.ExportSpecifier: - return (node as ImportOrExportSpecifier).isTypeOnly || (node as ImportOrExportSpecifier).parent.parent.isTypeOnly; + return (node as ImportSpecifier).isTypeOnly || (node as ImportSpecifier).parent.parent.isTypeOnly; case SyntaxKind.NamespaceImport: return (node as NamespaceImport).parent.isTypeOnly; case SyntaxKind.ImportClause: case SyntaxKind.ImportEqualsDeclaration: return (node as ImportClause | ImportEqualsDeclaration).isTypeOnly; + } + return false; +} + +export function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportDeclaration { + switch (node.kind) { + case SyntaxKind.ExportSpecifier: + return (node as ExportSpecifier).isTypeOnly || (node as ExportSpecifier).parent.parent.isTypeOnly; case SyntaxKind.ExportDeclaration: return (node as ExportDeclaration).isTypeOnly && !!(node as ExportDeclaration).moduleSpecifier && !(node as ExportDeclaration).exportClause; case SyntaxKind.NamespaceExport: return (node as NamespaceExport).parent.isTypeOnly; - default: - return false; } + return false; +} + +export function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration { + return isTypeOnlyImportDeclaration(node) || isTypeOnlyExportDeclaration(node); } export function isAssertionKey(node: Node): node is AssertionKey { diff --git a/src/services/completions.ts b/src/services/completions.ts index a166845ba3e97..e1be64a49bd95 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -227,6 +227,7 @@ import { isTypeLiteralNode, isTypeNode, isTypeOfExpression, + isTypeOnlyImportDeclaration, isTypeOnlyImportOrExportDeclaration, isTypeReferenceType, isValidTypeOnlyAliasUseSite, @@ -351,7 +352,7 @@ import { typeHasCallOrConstructSignatures, TypeLiteralNode, TypeNode, - TypeOnlyAliasDeclaration, + TypeOnlyImportDeclaration, TypeQueryNode, TypeReferenceNode, unescapeLeadingUnderscores, @@ -466,8 +467,8 @@ interface SymbolOriginInfoResolvedExport extends SymbolOriginInfo { moduleSpecifier: string; } -interface SymbolOriginInfoTypeOnlyAlias extends SymbolOriginInfo { - declaration: TypeOnlyAliasDeclaration; +interface SymbolOriginInfoTypeOnlyImport extends SymbolOriginInfo { + declaration: TypeOnlyImportDeclaration; } interface SymbolOriginInfoObjectLiteralMethod extends SymbolOriginInfo { @@ -508,7 +509,7 @@ function originIsNullableMember(origin: SymbolOriginInfo): boolean { return !!(origin.kind & SymbolOriginInfoKind.Nullable); } -function originIsTypeOnlyAlias(origin: SymbolOriginInfo | undefined): origin is SymbolOriginInfoTypeOnlyAlias { +function originIsTypeOnlyAlias(origin: SymbolOriginInfo | undefined): origin is SymbolOriginInfoTypeOnlyImport { return !!(origin && origin.kind & SymbolOriginInfoKind.TypeOnlyAlias); } @@ -3330,9 +3331,9 @@ function getCompletionData( symbolToSortTextMap[getSymbolId(symbol)] = SortText.GlobalsOrKeywords; } if (typeOnlyAliasNeedsPromotion && !(symbol.flags & SymbolFlags.Value)) { - const typeOnlyAliasDeclaration = symbol.declarations && find(symbol.declarations, isTypeOnlyImportOrExportDeclaration); + const typeOnlyAliasDeclaration = symbol.declarations && find(symbol.declarations, isTypeOnlyImportDeclaration); if (typeOnlyAliasDeclaration) { - const origin: SymbolOriginInfoTypeOnlyAlias = { kind: SymbolOriginInfoKind.TypeOnlyAlias, declaration: typeOnlyAliasDeclaration }; + const origin: SymbolOriginInfoTypeOnlyImport = { kind: SymbolOriginInfoKind.TypeOnlyAlias, declaration: typeOnlyAliasDeclaration }; symbolToOriginInfoMap[i] = origin; } } From ef6162dff4489404ab00e0b98a44337cbec79b29 Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 15:39:15 -0800 Subject: [PATCH 4/8] Update API --- .../reference/api/tsserverlibrary.d.ts | 18 ++++++++++++++---- tests/baselines/reference/api/typescript.d.ts | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 0884b10602045..1f1c14103a37a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5713,8 +5713,8 @@ declare namespace ts { readonly name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; - type TypeOnlyAliasDeclaration = ImportClause & { + type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport; + type TypeOnlyImportDeclaration = ImportClause & { readonly isTypeOnly: true; readonly name: Identifier; } | ImportEqualsDeclaration & { @@ -5731,7 +5731,8 @@ declare namespace ts { readonly isTypeOnly: true; }; }; - }) | ExportSpecifier & ({ + }); + type TypeOnlyExportDeclaration = ExportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedExports & { @@ -5739,7 +5740,14 @@ declare namespace ts { readonly isTypeOnly: true; }; }; - }); + }) | ExportDeclaration & { + readonly isTypeOnly: true; + } | NamespaceExport & { + readonly parent: ExportDeclaration & { + readonly isTypeOnly: true; + }; + }; + type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -8732,6 +8740,8 @@ 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 isTypeOnlyImportDeclaration(node: Node): node is TypeOnlyImportDeclaration; + function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportDeclaration; function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration; function isAssertionKey(node: Node): node is AssertionKey; function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 107407bd58e53..073257f8d4431 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1778,8 +1778,8 @@ declare namespace ts { readonly name: Identifier; } type ImportOrExportSpecifier = ImportSpecifier | ExportSpecifier; - type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier; - type TypeOnlyAliasDeclaration = ImportClause & { + type TypeOnlyCompatibleAliasDeclaration = ImportClause | ImportEqualsDeclaration | NamespaceImport | ImportOrExportSpecifier | ExportDeclaration | NamespaceExport; + type TypeOnlyImportDeclaration = ImportClause & { readonly isTypeOnly: true; readonly name: Identifier; } | ImportEqualsDeclaration & { @@ -1796,7 +1796,8 @@ declare namespace ts { readonly isTypeOnly: true; }; }; - }) | ExportSpecifier & ({ + }); + type TypeOnlyExportDeclaration = ExportSpecifier & ({ readonly isTypeOnly: true; } | { readonly parent: NamedExports & { @@ -1804,7 +1805,14 @@ declare namespace ts { readonly isTypeOnly: true; }; }; - }); + }) | ExportDeclaration & { + readonly isTypeOnly: true; + } | NamespaceExport & { + readonly parent: ExportDeclaration & { + readonly isTypeOnly: true; + }; + }; + type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; /** * This is either an `export =` or an `export default` declaration. * Unless `isExportEquals` is set, this node was parsed as an `export default`. @@ -4797,6 +4805,8 @@ 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 isTypeOnlyImportDeclaration(node: Node): node is TypeOnlyImportDeclaration; + function isTypeOnlyExportDeclaration(node: Node): node is TypeOnlyExportDeclaration; function isTypeOnlyImportOrExportDeclaration(node: Node): node is TypeOnlyAliasDeclaration; function isAssertionKey(node: Node): node is AssertionKey; function isStringTextContainingNode(node: Node): node is StringLiteral | TemplateLiteralToken; From 09f7087c000665463f2130151cbd80d982854130 Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 15:40:07 -0800 Subject: [PATCH 5/8] Update old test --- tests/baselines/reference/exportNamespace4.errors.txt | 10 +++++++--- tests/baselines/reference/exportNamespace4.js | 7 +++---- tests/baselines/reference/exportNamespace4.symbols | 4 ++-- tests/baselines/reference/exportNamespace4.types | 4 ++-- .../externalModules/typeOnly/exportNamespace4.ts | 4 ++-- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/baselines/reference/exportNamespace4.errors.txt b/tests/baselines/reference/exportNamespace4.errors.txt index 198589903ffed..353b26b773aa8 100644 --- a/tests/baselines/reference/exportNamespace4.errors.txt +++ b/tests/baselines/reference/exportNamespace4.errors.txt @@ -1,14 +1,15 @@ tests/cases/conformance/externalModules/typeOnly/d.ts(2,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +tests/cases/conformance/externalModules/typeOnly/e.ts(2,1): error TS1362: 'ns' cannot be used as a value because it was exported using 'export type'. ==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ==== export class A {} ==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ==== - export type * from './a'; // Grammar error + export type * from './a'; ==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ==== - export type * as ns from './a'; // Grammar error + export type * as ns from './a'; ==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ==== import { A } from './b'; @@ -17,7 +18,10 @@ tests/cases/conformance/externalModules/typeOnly/d.ts(2,1): error TS1362: 'A' ca !!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. !!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:1:1: 'A' was exported here. -==== tests/cases/conformance/externalModules/typeOnly/e.ts (0 errors) ==== +==== tests/cases/conformance/externalModules/typeOnly/e.ts (1 errors) ==== import { ns } from './c'; ns.A; + ~~ +!!! error TS1362: 'ns' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/c.ts:1:13: 'ns' was exported here. \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace4.js b/tests/baselines/reference/exportNamespace4.js index 31e2d8442d07a..faa416399761b 100644 --- a/tests/baselines/reference/exportNamespace4.js +++ b/tests/baselines/reference/exportNamespace4.js @@ -4,10 +4,10 @@ export class A {} //// [b.ts] -export type * from './a'; // Grammar error +export type * from './a'; //// [c.ts] -export type * as ns from './a'; // Grammar error +export type * as ns from './a'; //// [d.ts] import { A } from './b'; @@ -41,5 +41,4 @@ A; //// [e.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var c_1 = require("./c"); -c_1.ns.A; +ns.A; diff --git a/tests/baselines/reference/exportNamespace4.symbols b/tests/baselines/reference/exportNamespace4.symbols index 7e4d3712c41d9..aed58d785648d 100644 --- a/tests/baselines/reference/exportNamespace4.symbols +++ b/tests/baselines/reference/exportNamespace4.symbols @@ -4,10 +4,10 @@ export class A {} === tests/cases/conformance/externalModules/typeOnly/b.ts === -export type * from './a'; // Grammar error +export type * from './a'; === tests/cases/conformance/externalModules/typeOnly/c.ts === -export type * as ns from './a'; // Grammar error +export type * as ns from './a'; >ns : Symbol(ns, Decl(c.ts, 0, 11)) === tests/cases/conformance/externalModules/typeOnly/d.ts === diff --git a/tests/baselines/reference/exportNamespace4.types b/tests/baselines/reference/exportNamespace4.types index d1a496dad809d..397948eae7ca6 100644 --- a/tests/baselines/reference/exportNamespace4.types +++ b/tests/baselines/reference/exportNamespace4.types @@ -4,10 +4,10 @@ export class A {} === tests/cases/conformance/externalModules/typeOnly/b.ts === -export type * from './a'; // Grammar error +export type * from './a'; === tests/cases/conformance/externalModules/typeOnly/c.ts === -export type * as ns from './a'; // Grammar error +export type * as ns from './a'; >ns : typeof import("tests/cases/conformance/externalModules/typeOnly/a") === tests/cases/conformance/externalModules/typeOnly/d.ts === diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts index 889552e6643fe..1cf51dc69cba0 100644 --- a/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts @@ -2,10 +2,10 @@ export class A {} // @Filename: b.ts -export type * from './a'; // Grammar error +export type * from './a'; // @Filename: c.ts -export type * as ns from './a'; // Grammar error +export type * as ns from './a'; // @Filename: d.ts import { A } from './b'; From 3b6a1854b4b49ef91bc41369d938af1af4359752 Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 12 Jan 2023 15:41:13 -0800 Subject: [PATCH 6/8] Update diagnostic baseline --- .../tsserver/plugins/getSupportedCodeFixes-can-be-proxied.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/baselines/reference/tsserver/plugins/getSupportedCodeFixes-can-be-proxied.js b/tests/baselines/reference/tsserver/plugins/getSupportedCodeFixes-can-be-proxied.js index eaf791e9d05d7..252ccc4e6c1fc 100644 --- a/tests/baselines/reference/tsserver/plugins/getSupportedCodeFixes-can-be-proxied.js +++ b/tests/baselines/reference/tsserver/plugins/getSupportedCodeFixes-can-be-proxied.js @@ -678,7 +678,6 @@ Info 32 [00:01:13.000] response: "1368", "1379", "1380", - "1383", "1385", "1386", "1387", @@ -2012,7 +2011,6 @@ Info 38 [00:01:19.000] response: "1368", "1379", "1380", - "1383", "1385", "1386", "1387", @@ -3258,7 +3256,6 @@ Info 40 [00:01:21.000] response: "1368", "1379", "1380", - "1383", "1385", "1386", "1387", From 4a5917b254059c5b20038f0e0d0fb46d28de7e18 Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Thu, 19 Jan 2023 11:41:37 -0800 Subject: [PATCH 7/8] Add declaration emit to baselines, verify syntax is an error in JS --- tests/baselines/reference/exportNamespace4.js | 13 ++++++ tests/baselines/reference/exportNamespace5.js | 19 +++++++++ .../reference/exportNamespace_js.errors.txt | 19 +++++++++ .../baselines/reference/exportNamespace_js.js | 40 +++++++++++++++++++ .../reference/exportNamespace_js.symbols | 15 +++++++ .../reference/exportNamespace_js.types | 15 +++++++ .../typeOnly/exportNamespace4.ts | 2 + .../typeOnly/exportNamespace5.ts | 2 + .../typeOnly/exportNamespace_js.ts | 14 +++++++ 9 files changed, 139 insertions(+) create mode 100644 tests/baselines/reference/exportNamespace_js.errors.txt create mode 100644 tests/baselines/reference/exportNamespace_js.js create mode 100644 tests/baselines/reference/exportNamespace_js.symbols create mode 100644 tests/baselines/reference/exportNamespace_js.types create mode 100644 tests/cases/conformance/externalModules/typeOnly/exportNamespace_js.ts diff --git a/tests/baselines/reference/exportNamespace4.js b/tests/baselines/reference/exportNamespace4.js index faa416399761b..fa6b5d9372097 100644 --- a/tests/baselines/reference/exportNamespace4.js +++ b/tests/baselines/reference/exportNamespace4.js @@ -42,3 +42,16 @@ A; "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); ns.A; + + +//// [a.d.ts] +export declare class A { +} +//// [b.d.ts] +export type * from './a'; +//// [c.d.ts] +export type * as ns from './a'; +//// [d.d.ts] +export {}; +//// [e.d.ts] +export {}; diff --git a/tests/baselines/reference/exportNamespace5.js b/tests/baselines/reference/exportNamespace5.js index ae61f9da7236d..a1ec261fa8b80 100644 --- a/tests/baselines/reference/exportNamespace5.js +++ b/tests/baselines/reference/exportNamespace5.js @@ -85,3 +85,22 @@ var d_1 = require("./d"); var _ = new d_1.A(); // Ok var __ = new d_1.B(); // Ok var ___ = new d_1.X(); // Ok + + +//// [a.d.ts] +export declare class A { +} +export declare class B { +} +export declare class X { +} +//// [b.d.ts] +export type * from "./a"; +export { X } from "./a"; +//// [c.d.ts] +export {}; +//// [d.d.ts] +export type * from "./a"; +export * from "./a"; +//// [e.d.ts] +export {}; diff --git a/tests/baselines/reference/exportNamespace_js.errors.txt b/tests/baselines/reference/exportNamespace_js.errors.txt new file mode 100644 index 0000000000000..32764f3e57c3e --- /dev/null +++ b/tests/baselines/reference/exportNamespace_js.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/externalModules/typeOnly/b.js(1,1): error TS8006: 'export type' declarations can only be used in TypeScript files. +tests/cases/conformance/externalModules/typeOnly/c.js(2,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. + + +==== tests/cases/conformance/externalModules/typeOnly/a.js (0 errors) ==== + export class A {} + +==== tests/cases/conformance/externalModules/typeOnly/b.js (1 errors) ==== + export type * from './a'; + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS8006: 'export type' declarations can only be used in TypeScript files. + +==== tests/cases/conformance/externalModules/typeOnly/c.js (1 errors) ==== + import { A } from './b'; + A; + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.js:1:1: 'A' was exported here. + \ No newline at end of file diff --git a/tests/baselines/reference/exportNamespace_js.js b/tests/baselines/reference/exportNamespace_js.js new file mode 100644 index 0000000000000..95e8c9e059702 --- /dev/null +++ b/tests/baselines/reference/exportNamespace_js.js @@ -0,0 +1,40 @@ +//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace_js.ts] //// + +//// [a.js] +export class A {} + +//// [b.js] +export type * from './a'; + +//// [c.js] +import { A } from './b'; +A; + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [c.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var b_1 = require("./b"); +A; + + +//// [a.d.ts] +export class A { +} +//// [b.d.ts] +export * from "./a"; +//// [c.d.ts] +export {}; diff --git a/tests/baselines/reference/exportNamespace_js.symbols b/tests/baselines/reference/exportNamespace_js.symbols new file mode 100644 index 0000000000000..475710b68489e --- /dev/null +++ b/tests/baselines/reference/exportNamespace_js.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.js === +export class A {} +>A : Symbol(A, Decl(a.js, 0, 0)) + +=== tests/cases/conformance/externalModules/typeOnly/b.js === + +export type * from './a'; + +=== tests/cases/conformance/externalModules/typeOnly/c.js === +import { A } from './b'; +>A : Symbol(A, Decl(c.js, 0, 8)) + +A; +>A : Symbol(A, Decl(c.js, 0, 8)) + diff --git a/tests/baselines/reference/exportNamespace_js.types b/tests/baselines/reference/exportNamespace_js.types new file mode 100644 index 0000000000000..3205448594836 --- /dev/null +++ b/tests/baselines/reference/exportNamespace_js.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/externalModules/typeOnly/a.js === +export class A {} +>A : A + +=== tests/cases/conformance/externalModules/typeOnly/b.js === + +export type * from './a'; + +=== tests/cases/conformance/externalModules/typeOnly/c.js === +import { A } from './b'; +>A : typeof A + +A; +>A : typeof A + diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts index 1cf51dc69cba0..1cb1c1f0d9539 100644 --- a/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace4.ts @@ -1,3 +1,5 @@ +// @declaration: true + // @Filename: a.ts export class A {} diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts index c085d6ced438c..fd4d392fb589f 100644 --- a/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace5.ts @@ -1,3 +1,5 @@ +// @declaration: true + // @Filename: /a.ts export class A {} export class B {} diff --git a/tests/cases/conformance/externalModules/typeOnly/exportNamespace_js.ts b/tests/cases/conformance/externalModules/typeOnly/exportNamespace_js.ts new file mode 100644 index 0000000000000..3e02cecc306de --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/exportNamespace_js.ts @@ -0,0 +1,14 @@ +// @declaration: true +// @outDir: out +// @checkJs: true +// @allowJs: true + +// @Filename: a.js +export class A {} + +// @Filename: b.js +export type * from './a'; + +// @Filename: c.js +import { A } from './b'; +A; From 271418fa714b93a0ff5826b7171b949dcb8d6acc Mon Sep 17 00:00:00 2001 From: Andrew Branch <andrew@wheream.io> Date: Fri, 20 Jan 2023 13:31:14 -0800 Subject: [PATCH 8/8] Preserve `type` in dts even when it came from JS --- src/compiler/checker.ts | 2 +- tests/baselines/reference/exportNamespace_js.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b47ae45f0351f..d20aca210332f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8553,7 +8553,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { for (const node of symbol.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); if (!resolvedModule) continue; - addResult(factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); + addResult(factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ (node as ExportDeclaration).isTypeOnly, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); } } } diff --git a/tests/baselines/reference/exportNamespace_js.js b/tests/baselines/reference/exportNamespace_js.js index 95e8c9e059702..4e64bdc174398 100644 --- a/tests/baselines/reference/exportNamespace_js.js +++ b/tests/baselines/reference/exportNamespace_js.js @@ -35,6 +35,6 @@ A; export class A { } //// [b.d.ts] -export * from "./a"; +export type * from "./a"; //// [c.d.ts] export {};