Skip to content

Commit 32d5825

Browse files
committed
Add "A module cannot have multiple default exports." message for multiple "default" exports
1 parent 738b26f commit 32d5825

11 files changed

+125
-7
lines changed

src/compiler/binder.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,9 @@ namespace ts {
185185
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
186186
Debug.assert(!hasDynamicName(node));
187187

188+
let isDefaultExport = node.flags & NodeFlags.Default;
188189
// The exported symbol for an export default function/class node is always named "default"
189-
let name = node.flags & NodeFlags.Default && parent ? "default" : getDeclarationName(node);
190+
let name = isDefaultExport && parent ? "default" : getDeclarationName(node);
190191

191192
let symbol: Symbol;
192193
if (name !== undefined) {
@@ -227,6 +228,13 @@ namespace ts {
227228
let message = symbol.flags & SymbolFlags.BlockScopedVariable
228229
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
229230
: Diagnostics.Duplicate_identifier_0;
231+
232+
forEach(symbol.declarations, declaration => {
233+
if (declaration.flags & NodeFlags.Default) {
234+
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
235+
}
236+
});
237+
230238
forEach(symbol.declarations, declaration => {
231239
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
232240
});

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,10 @@
16561656
"category": "Error",
16571657
"code": 2527
16581658
},
1659+
"A module cannot have multiple default exports.": {
1660+
"category": "Error",
1661+
"code": 2528
1662+
},
16591663
"JSX element attributes type '{0}' must be an object type.": {
16601664
"category": "Error",
16611665
"code": 2600
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [defaultExportWithOverloads01.ts]
2+
3+
export default function f();
4+
export default function f(x: string);
5+
export default function f(...args: any[]) {
6+
}
7+
8+
//// [defaultExportWithOverloads01.js]
9+
function f() {
10+
var args = [];
11+
for (var _i = 0; _i < arguments.length; _i++) {
12+
args[_i - 0] = arguments[_i];
13+
}
14+
}
15+
Object.defineProperty(exports, "__esModule", { value: true });
16+
exports.default = f;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts ===
2+
3+
export default function f();
4+
>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37))
5+
6+
export default function f(x: string);
7+
>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37))
8+
>x : Symbol(x, Decl(defaultExportWithOverloads01.ts, 2, 26))
9+
10+
export default function f(...args: any[]) {
11+
>f : Symbol(f, Decl(defaultExportWithOverloads01.ts, 0, 0), Decl(defaultExportWithOverloads01.ts, 1, 28), Decl(defaultExportWithOverloads01.ts, 2, 37))
12+
>args : Symbol(args, Decl(defaultExportWithOverloads01.ts, 3, 26))
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/conformance/es6/modules/defaultExportWithOverloads01.ts ===
2+
3+
export default function f();
4+
>f : { (): any; (x: string): any; }
5+
6+
export default function f(x: string);
7+
>f : { (): any; (x: string): any; }
8+
>x : string
9+
10+
export default function f(...args: any[]) {
11+
>f : { (): any; (x: string): any; }
12+
>args : any[]
13+
}

tests/baselines/reference/multipleDefaultExports01.errors.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2300: Duplicate identifier 'foo'.
2-
tests/cases/conformance/es6/modules/m1.ts(6,25): error TS2300: Duplicate identifier 'bar'.
3-
tests/cases/conformance/es6/modules/m1.ts(11,1): error TS2300: Duplicate identifier 'default'.
1+
tests/cases/conformance/es6/modules/m1.ts(2,22): error TS2528: A module cannot have multiple default exports.
2+
tests/cases/conformance/es6/modules/m1.ts(6,25): error TS2528: A module cannot have multiple default exports.
3+
tests/cases/conformance/es6/modules/m1.ts(11,1): error TS2528: A module cannot have multiple default exports.
44
tests/cases/conformance/es6/modules/m2.ts(3,1): error TS2348: Value of type 'typeof foo' is not callable. Did you mean to include 'new'?
55

66

77
==== tests/cases/conformance/es6/modules/m1.ts (3 errors) ====
88

99
export default class foo {
1010
~~~
11-
!!! error TS2300: Duplicate identifier 'foo'.
11+
!!! error TS2528: A module cannot have multiple default exports.
1212

1313
}
1414

1515
export default function bar() {
1616
~~~
17-
!!! error TS2300: Duplicate identifier 'bar'.
17+
!!! error TS2528: A module cannot have multiple default exports.
1818

1919
}
2020

2121
var x = 10;
2222
export default x;
2323
~~~~~~~~~~~~~~~~~
24-
!!! error TS2300: Duplicate identifier 'default'.
24+
!!! error TS2528: A module cannot have multiple default exports.
2525

2626
==== tests/cases/conformance/es6/modules/m2.ts (1 errors) ====
2727
import Entity from "./m1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [tests/cases/conformance/es6/modules/multipleDefaultExports03.ts] ////
2+
3+
//// [m1.ts]
4+
5+
export default class C {
6+
}
7+
8+
//// [m2.ts]
9+
export default class C {
10+
}
11+
12+
//// [m1.js]
13+
var C = (function () {
14+
function C() {
15+
}
16+
return C;
17+
})();
18+
Object.defineProperty(exports, "__esModule", { value: true });
19+
exports.default = C;
20+
//// [m2.js]
21+
var C = (function () {
22+
function C() {
23+
}
24+
return C;
25+
})();
26+
Object.defineProperty(exports, "__esModule", { value: true });
27+
exports.default = C;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/conformance/es6/modules/m1.ts ===
2+
3+
export default class C {
4+
>C : Symbol(C, Decl(m1.ts, 0, 0))
5+
}
6+
7+
=== tests/cases/conformance/es6/modules/m2.ts ===
8+
export default class C {
9+
>C : Symbol(C, Decl(m2.ts, 0, 0))
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
=== tests/cases/conformance/es6/modules/m1.ts ===
2+
3+
export default class C {
4+
>C : C
5+
}
6+
7+
=== tests/cases/conformance/es6/modules/m2.ts ===
8+
export default class C {
9+
>C : C
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @module: commonjs
2+
// @target: ES5
3+
4+
export default function f();
5+
export default function f(x: string);
6+
export default function f(...args: any[]) {
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @module: commonjs
2+
// @target: ES5
3+
4+
// @filename: m1.ts
5+
export default class C {
6+
}
7+
8+
// @filename: m2.ts
9+
export default class C {
10+
}

0 commit comments

Comments
 (0)