diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 63d9ca101fc..572993e4560 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1792,6 +1792,7 @@ namespace ts { !checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg!) && // TODO: GH#18217 !checkAndReportErrorForExtendingInterface(errorLocation) && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && + !checkAndReportErrorForExportingPrimitiveType(errorLocation, name) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) { @@ -2053,9 +2054,21 @@ namespace ts { return false; } + function isPrimitiveTypeName(name: __String) { + return name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never" || name === "unknown"; + } + + function checkAndReportErrorForExportingPrimitiveType(errorLocation: Node, name: __String): boolean { + if (isPrimitiveTypeName(name) && errorLocation.parent.kind === SyntaxKind.ExportSpecifier) { + error(errorLocation, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name as string); + return true; + } + return false; + } + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { - if (name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never") { + if (isPrimitiveTypeName(name)) { error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); return true; } @@ -33300,6 +33313,7 @@ namespace ts { const id = node.expression as Identifier; const sym = resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node); if (sym) { + markAliasReferenced(sym, id); // If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`) const target = sym.flags & SymbolFlags.Alias ? resolveAlias(sym) : sym; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e6a384b45c3..43077e61e68 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1127,6 +1127,7 @@ "category": "Error", "code": 1378 }, + "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 diff --git a/tests/baselines/reference/exportNonLocalDeclarations.errors.txt b/tests/baselines/reference/exportNonLocalDeclarations.errors.txt new file mode 100644 index 00000000000..fc922d7a536 --- /dev/null +++ b/tests/baselines/reference/exportNonLocalDeclarations.errors.txt @@ -0,0 +1,12 @@ +tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts(1,10): error TS2661: Cannot export 'string'. Only local declarations can be exported from a module. +tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts(2,15): error TS2661: Cannot export 'number'. Only local declarations can be exported from a module. + + +==== tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts (2 errors) ==== + export { string }; + ~~~~~~ +!!! error TS2661: Cannot export 'string'. Only local declarations can be exported from a module. + export type { number }; + ~~~~~~ +!!! error TS2661: Cannot export 'number'. Only local declarations can be exported from a module. + \ No newline at end of file diff --git a/tests/baselines/reference/exportNonLocalDeclarations.js b/tests/baselines/reference/exportNonLocalDeclarations.js new file mode 100644 index 00000000000..946ad5fa550 --- /dev/null +++ b/tests/baselines/reference/exportNonLocalDeclarations.js @@ -0,0 +1,8 @@ +//// [exportNonLocalDeclarations.ts] +export { string }; +export type { number }; + + +//// [exportNonLocalDeclarations.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/exportNonLocalDeclarations.symbols b/tests/baselines/reference/exportNonLocalDeclarations.symbols new file mode 100644 index 00000000000..7f1d823b495 --- /dev/null +++ b/tests/baselines/reference/exportNonLocalDeclarations.symbols @@ -0,0 +1,7 @@ +=== tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts === +export { string }; +>string : Symbol(string, Decl(exportNonLocalDeclarations.ts, 0, 8)) + +export type { number }; +>number : Symbol(number, Decl(exportNonLocalDeclarations.ts, 1, 13)) + diff --git a/tests/baselines/reference/exportNonLocalDeclarations.types b/tests/baselines/reference/exportNonLocalDeclarations.types new file mode 100644 index 00000000000..5a2e4a3ad2a --- /dev/null +++ b/tests/baselines/reference/exportNonLocalDeclarations.types @@ -0,0 +1,7 @@ +=== tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts === +export { string }; +>string : any + +export type { number }; +>number : any + diff --git a/tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts b/tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts new file mode 100644 index 00000000000..76d528e8bee --- /dev/null +++ b/tests/cases/conformance/externalModules/exportNonLocalDeclarations.ts @@ -0,0 +1,2 @@ +export { string }; +export type { number };