diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 712c96a49f93b..04dc4011a1591 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1512,7 +1512,7 @@ namespace ts { errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); } if (isExternalModuleAugmentation(node)) { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes); + declareModuleSymbol(node); } else { let pattern: Pattern | undefined; @@ -1534,12 +1534,8 @@ namespace ts { } } else { - const state = getModuleInstanceState(node); - if (state === ModuleInstanceState.NonInstantiated) { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes); - } - else { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes); + const state = declareModuleSymbol(node); + if (state !== ModuleInstanceState.NonInstantiated) { if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) { // if module was already merged with some function, class or non-const enum // treat is a non-const-enum-only @@ -1560,6 +1556,15 @@ namespace ts { } } + function declareModuleSymbol(node: ModuleDeclaration): ModuleInstanceState { + const state = getModuleInstanceState(node); + const instantiated = state !== ModuleInstanceState.NonInstantiated; + declareSymbolAndAddToSymbolTable(node, + instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule, + instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes); + return state; + } + function bindFunctionOrConstructorType(node: SignatureDeclaration): void { // For a given function symbol "<...>(...) => T" we want to generate a symbol identical // to the one we would get for: { <...>(...): T } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7fbcea6bee2f5..a09b63d46fd0a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -486,6 +486,9 @@ namespace ts { } recordMergedSymbol(target, source); } + else if (target.flags & SymbolFlags.NamespaceModule) { + error(source.valueDeclaration.name, Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + } else { const message = target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4278784e9abf4..43a9cce4de6e6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1823,6 +1823,10 @@ "category": "Error", "code": 2609 }, + "Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": { + "category": "Error", + "code": 2649 + }, "Cannot emit namespaced JSX elements in React": { "category": "Error", "code": 2650 diff --git a/tests/baselines/reference/augmentExportEquals7.errors.txt b/tests/baselines/reference/augmentExportEquals7.errors.txt new file mode 100644 index 0000000000000..e13cf03702386 --- /dev/null +++ b/tests/baselines/reference/augmentExportEquals7.errors.txt @@ -0,0 +1,16 @@ +/node_modules/@types/lib-extender/index.d.ts(2,16): error TS2649: Cannot augment module 'lib' with value exports because it resolves to a non-module entity. + + +==== /node_modules/lib/index.d.ts (0 errors) ==== + declare var lib: () => void; + declare namespace lib {} + export = lib; + +==== /node_modules/@types/lib-extender/index.d.ts (1 errors) ==== + import * as lib from "lib"; + declare module "lib" { + ~~~~~ +!!! error TS2649: Cannot augment module 'lib' with value exports because it resolves to a non-module entity. + export function fn(): void; + } + \ No newline at end of file diff --git a/tests/baselines/reference/globalAugmentationModuleResolution.types b/tests/baselines/reference/globalAugmentationModuleResolution.types index c057ea2943db4..75f23b0cd6b81 100644 --- a/tests/baselines/reference/globalAugmentationModuleResolution.types +++ b/tests/baselines/reference/globalAugmentationModuleResolution.types @@ -3,7 +3,7 @@ export { }; declare global { ->global : any +>global : typeof global var x: number; >x : number diff --git a/tests/cases/compiler/augmentExportEquals7.ts b/tests/cases/compiler/augmentExportEquals7.ts new file mode 100644 index 0000000000000..c287bcbe8c474 --- /dev/null +++ b/tests/cases/compiler/augmentExportEquals7.ts @@ -0,0 +1,10 @@ +// @Filename: /node_modules/lib/index.d.ts +declare var lib: () => void; +declare namespace lib {} +export = lib; + +// @Filename: /node_modules/@types/lib-extender/index.d.ts +import * as lib from "lib"; +declare module "lib" { + export function fn(): void; +}