Skip to content

Commit 5ef6192

Browse files
authored
Allow export default interface. Related to issue 3792. (#16040)
* Allow export default interface. Related to issue 3792. * Update exportDefaultAbstractClass test * Allow default export to be a non-value for lookup purposes * Add local usage to exportDefaultInterface test
1 parent 23b2545 commit 5ef6192

10 files changed

+215
-17
lines changed

src/compiler/parser.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,12 +1240,12 @@ namespace ts {
12401240
if (token() === SyntaxKind.ExportKeyword) {
12411241
nextToken();
12421242
if (token() === SyntaxKind.DefaultKeyword) {
1243-
return lookAhead(nextTokenIsClassOrFunctionOrAsync);
1243+
return lookAhead(nextTokenCanFollowDefaultKeyword);
12441244
}
12451245
return token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier();
12461246
}
12471247
if (token() === SyntaxKind.DefaultKeyword) {
1248-
return nextTokenIsClassOrFunctionOrAsync();
1248+
return nextTokenCanFollowDefaultKeyword();
12491249
}
12501250
if (token() === SyntaxKind.StaticKeyword) {
12511251
nextToken();
@@ -1267,9 +1267,10 @@ namespace ts {
12671267
|| isLiteralPropertyName();
12681268
}
12691269

1270-
function nextTokenIsClassOrFunctionOrAsync(): boolean {
1270+
function nextTokenCanFollowDefaultKeyword(): boolean {
12711271
nextToken();
12721272
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
1273+
token() === SyntaxKind.InterfaceKeyword ||
12731274
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
12741275
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
12751276
}

src/compiler/utilities.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3168,11 +3168,11 @@ namespace ts {
31683168
}
31693169

31703170
export function getLocalSymbolForExportDefault(symbol: Symbol) {
3171-
return isExportDefaultSymbol(symbol) ? symbol.valueDeclaration.localSymbol : undefined;
3171+
return isExportDefaultSymbol(symbol) ? symbol.declarations[0].localSymbol : undefined;
31723172
}
31733173

31743174
function isExportDefaultSymbol(symbol: Symbol): boolean {
3175-
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default);
3175+
return symbol && length(symbol.declarations) > 0 && hasModifier(symbol.declarations[0], ModifierFlags.Default);
31763176
}
31773177

31783178
/** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */
Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,63 @@
11
//// [tests/cases/compiler/exportDefaultAbstractClass.ts] ////
22

33
//// [a.ts]
4-
export default abstract class A {}
4+
export default abstract class A { a: number; }
5+
6+
class B extends A {}
7+
new B().a.toExponential();
58

69
//// [b.ts]
7-
import A from './a'
8-
10+
import A from './a';
11+
12+
class C extends A {}
13+
new C().a.toExponential();
914

1015
//// [a.js]
1116
"use strict";
17+
var __extends = (this && this.__extends) || (function () {
18+
var extendStatics = Object.setPrototypeOf ||
19+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
20+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
21+
return function (d, b) {
22+
extendStatics(d, b);
23+
function __() { this.constructor = d; }
24+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
25+
};
26+
})();
1227
exports.__esModule = true;
1328
var A = (function () {
1429
function A() {
1530
}
1631
return A;
1732
}());
1833
exports["default"] = A;
34+
var B = (function (_super) {
35+
__extends(B, _super);
36+
function B() {
37+
return _super !== null && _super.apply(this, arguments) || this;
38+
}
39+
return B;
40+
}(A));
41+
new B().a.toExponential();
1942
//// [b.js]
2043
"use strict";
44+
var __extends = (this && this.__extends) || (function () {
45+
var extendStatics = Object.setPrototypeOf ||
46+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
47+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
48+
return function (d, b) {
49+
extendStatics(d, b);
50+
function __() { this.constructor = d; }
51+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
52+
};
53+
})();
2154
exports.__esModule = true;
55+
var a_1 = require("./a");
56+
var C = (function (_super) {
57+
__extends(C, _super);
58+
function C() {
59+
return _super !== null && _super.apply(this, arguments) || this;
60+
}
61+
return C;
62+
}(a_1["default"]));
63+
new C().a.toExponential();
Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,31 @@
11
=== tests/cases/compiler/a.ts ===
2-
export default abstract class A {}
2+
export default abstract class A { a: number; }
33
>A : Symbol(A, Decl(a.ts, 0, 0))
4+
>a : Symbol(A.a, Decl(a.ts, 0, 33))
5+
6+
class B extends A {}
7+
>B : Symbol(B, Decl(a.ts, 0, 46))
8+
>A : Symbol(A, Decl(a.ts, 0, 0))
9+
10+
new B().a.toExponential();
11+
>new B().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
12+
>new B().a : Symbol(A.a, Decl(a.ts, 0, 33))
13+
>B : Symbol(B, Decl(a.ts, 0, 46))
14+
>a : Symbol(A.a, Decl(a.ts, 0, 33))
15+
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
416

517
=== tests/cases/compiler/b.ts ===
6-
import A from './a'
18+
import A from './a';
719
>A : Symbol(A, Decl(b.ts, 0, 6))
820

21+
class C extends A {}
22+
>C : Symbol(C, Decl(b.ts, 0, 20))
23+
>A : Symbol(A, Decl(b.ts, 0, 6))
24+
25+
new C().a.toExponential();
26+
>new C().a.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
27+
>new C().a : Symbol(A.a, Decl(a.ts, 0, 33))
28+
>C : Symbol(C, Decl(b.ts, 0, 20))
29+
>a : Symbol(A.a, Decl(a.ts, 0, 33))
30+
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
31+
Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
11
=== tests/cases/compiler/a.ts ===
2-
export default abstract class A {}
2+
export default abstract class A { a: number; }
33
>A : A
4+
>a : number
5+
6+
class B extends A {}
7+
>B : B
8+
>A : A
9+
10+
new B().a.toExponential();
11+
>new B().a.toExponential() : string
12+
>new B().a.toExponential : (fractionDigits?: number) => string
13+
>new B().a : number
14+
>new B() : B
15+
>B : typeof B
16+
>a : number
17+
>toExponential : (fractionDigits?: number) => string
418

519
=== tests/cases/compiler/b.ts ===
6-
import A from './a'
20+
import A from './a';
721
>A : typeof A
822

23+
class C extends A {}
24+
>C : C
25+
>A : A
26+
27+
new C().a.toExponential();
28+
>new C().a.toExponential() : string
29+
>new C().a.toExponential : (fractionDigits?: number) => string
30+
>new C().a : number
31+
>new C() : C
32+
>C : typeof C
33+
>a : number
34+
>toExponential : (fractionDigits?: number) => string
35+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [tests/cases/compiler/exportDefaultInterface.ts] ////
2+
3+
//// [a.ts]
4+
export default interface A { value: number; }
5+
6+
var a: A;
7+
a.value.toExponential();
8+
9+
//// [b.ts]
10+
import A from './a';
11+
12+
var a: A;
13+
a.value.toExponential();
14+
15+
//// [a.js]
16+
"use strict";
17+
exports.__esModule = true;
18+
var a;
19+
a.value.toExponential();
20+
//// [b.js]
21+
"use strict";
22+
exports.__esModule = true;
23+
var a;
24+
a.value.toExponential();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
=== tests/cases/compiler/a.ts ===
2+
export default interface A { value: number; }
3+
>A : Symbol(A, Decl(a.ts, 0, 0))
4+
>value : Symbol(A.value, Decl(a.ts, 0, 28))
5+
6+
var a: A;
7+
>a : Symbol(a, Decl(a.ts, 2, 3))
8+
>A : Symbol(A, Decl(a.ts, 0, 0))
9+
10+
a.value.toExponential();
11+
>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
12+
>a.value : Symbol(A.value, Decl(a.ts, 0, 28))
13+
>a : Symbol(a, Decl(a.ts, 2, 3))
14+
>value : Symbol(A.value, Decl(a.ts, 0, 28))
15+
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
16+
17+
=== tests/cases/compiler/b.ts ===
18+
import A from './a';
19+
>A : Symbol(A, Decl(b.ts, 0, 6))
20+
21+
var a: A;
22+
>a : Symbol(a, Decl(b.ts, 2, 3))
23+
>A : Symbol(A, Decl(b.ts, 0, 6))
24+
25+
a.value.toExponential();
26+
>a.value.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
27+
>a.value : Symbol(A.value, Decl(a.ts, 0, 28))
28+
>a : Symbol(a, Decl(b.ts, 2, 3))
29+
>value : Symbol(A.value, Decl(a.ts, 0, 28))
30+
>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --))
31+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/a.ts ===
2+
export default interface A { value: number; }
3+
>A : A
4+
>value : number
5+
6+
var a: A;
7+
>a : A
8+
>A : A
9+
10+
a.value.toExponential();
11+
>a.value.toExponential() : string
12+
>a.value.toExponential : (fractionDigits?: number) => string
13+
>a.value : number
14+
>a : A
15+
>value : number
16+
>toExponential : (fractionDigits?: number) => string
17+
18+
=== tests/cases/compiler/b.ts ===
19+
import A from './a';
20+
>A : any
21+
22+
var a: A;
23+
>a : A
24+
>A : A
25+
26+
a.value.toExponential();
27+
>a.value.toExponential() : string
28+
>a.value.toExponential : (fractionDigits?: number) => string
29+
>a.value : number
30+
>a : A
31+
>value : number
32+
>toExponential : (fractionDigits?: number) => string
33+
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
// @filename: a.ts
2-
export default abstract class A {}
3-
4-
// @filename: b.ts
5-
import A from './a'
1+
// @Filename: a.ts
2+
export default abstract class A { a: number; }
3+
4+
class B extends A {}
5+
new B().a.toExponential();
6+
7+
// @Filename: b.ts
8+
import A from './a';
9+
10+
class C extends A {}
11+
new C().a.toExponential();
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @Filename: a.ts
2+
export default interface A { value: number; }
3+
4+
var a: A;
5+
a.value.toExponential();
6+
7+
// @Filename: b.ts
8+
import A from './a';
9+
10+
var a: A;
11+
a.value.toExponential();

0 commit comments

Comments
 (0)