Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,17 @@ namespace ts {
}

if (symbolFlags & SymbolFlags.Value) {
const { valueDeclaration } = symbol;
if (!valueDeclaration ||
(isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) ||
(valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) {
// other kinds of value declarations take precedence over modules and assignment declarations
symbol.valueDeclaration = node;
}
setValueDeclaration(symbol, node);
}
}

function setValueDeclaration(symbol: Symbol, node: Declaration): void {
const { valueDeclaration } = symbol;
if (!valueDeclaration ||
(isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) ||
(valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) {
// other kinds of value declarations take precedence over modules and assignment declarations
symbol.valueDeclaration = node;
}
}

Expand Down Expand Up @@ -2286,14 +2290,19 @@ namespace ts {
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)!);
}
else {
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node)
const flags = exportAssignmentIsAlias(node)
// An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression;
? SymbolFlags.Alias
// An export default clause with any other expression exports a value
: SymbolFlags.Property;
// If there is an `export default x;` alias declaration, can't `export default` anything else.
// (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.)
declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All);
const symbol = declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All);

if (node.isExportEquals) {
// Will be an error later, since the module already has other exports. Just make sure this has a valueDeclaration set.
setValueDeclaration(symbol, node);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
tests/cases/compiler/errorForConflictingExportEqualsValue.ts(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
/a.ts(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements.


==== tests/cases/compiler/errorForConflictingExportEqualsValue.ts (1 errors) ====
==== /a.ts (1 errors) ====
export var x;
export = {};
~~~~~~~~~~~~
export = x;
~~~~~~~~~~~
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
import("./a");

Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//// [errorForConflictingExportEqualsValue.ts]
//// [a.ts]
export var x;
export = {};
export = x;
import("./a");


//// [errorForConflictingExportEqualsValue.js]
//// [a.js]
"use strict";
module.exports = {};
Promise.resolve().then(function () { return require("./a"); });
module.exports = exports.x;
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
=== tests/cases/compiler/errorForConflictingExportEqualsValue.ts ===
=== /a.ts ===
export var x;
>x : Symbol(x, Decl(errorForConflictingExportEqualsValue.ts, 0, 10))
>x : Symbol(x, Decl(a.ts, 0, 10))

export = {};
export = x;
>x : Symbol(x, Decl(a.ts, 0, 10))

import("./a");
>"./a" : Symbol("/a", Decl(a.ts, 0, 0))

Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
=== tests/cases/compiler/errorForConflictingExportEqualsValue.ts ===
=== /a.ts ===
export var x;
>x : any

export = {};
>{} : {}
export = x;
>x : any

import("./a");
>import("./a") : Promise<typeof import("/a").x>
>"./a" : "./a"

5 changes: 4 additions & 1 deletion tests/cases/compiler/errorForConflictingExportEqualsValue.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// @lib: es6
// @Filename: /a.ts
export var x;
export = {};
export = x;
import("./a");