Skip to content

Commit dcbc478

Browse files
authored
Tighten heuristic for definite dts moduleness to check for syntactic default (#22814)
* Tighten heuristic for definite dts moduleness to check for syntactic default exports * Inline function
1 parent 36b49c0 commit dcbc478

5 files changed

+123
-3
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,14 +1730,19 @@ namespace ts {
17301730
: resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias);
17311731
}
17321732

1733+
function isSyntacticDefault(node: Node) {
1734+
return ((isExportAssignment(node) && !node.isExportEquals) || hasModifier(node, ModifierFlags.Default));
1735+
}
1736+
17331737
function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
17341738
if (!allowSyntheticDefaultImports) {
17351739
return false;
17361740
}
17371741
// Declaration files (and ambient modules)
17381742
if (!file || file.isDeclarationFile) {
1739-
// Definitely cannot have a synthetic default if they have a default member specified
1740-
if (resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias)) {
1743+
// Definitely cannot have a synthetic default if they have a syntactic default member specified
1744+
const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
1745+
if (defaultExportSymbol && defaultExportSymbol.valueDeclaration && isSyntacticDefault(defaultExportSymbol.valueDeclaration)) {
17411746
return false;
17421747
}
17431748
// It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
@@ -1777,7 +1782,7 @@ namespace ts {
17771782
if (!exportDefaultSymbol && !hasSyntheticDefault) {
17781783
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
17791784
}
1780-
else if (!exportDefaultSymbol && hasSyntheticDefault) {
1785+
else if (hasSyntheticDefault) {
17811786
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
17821787
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
17831788
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/compiler/esModuleInteropDefaultMemberMustBeSyntacticallyDefaultExport.ts] ////
2+
3+
//// [point.d.ts]
4+
declare class Point {
5+
x: number;
6+
y: number;
7+
8+
constructor(x: number, y: number);
9+
10+
static default: "foo";
11+
}
12+
13+
export = Point;
14+
//// [index.ts]
15+
import Point from "./point";
16+
17+
const C = Point;
18+
const p = new C(1, 2);
19+
20+
21+
//// [index.js]
22+
"use strict";
23+
var __importDefault = (this && this.__importDefault) || function (mod) {
24+
return (mod && mod.__esModule) ? mod : { "default": mod };
25+
};
26+
exports.__esModule = true;
27+
var point_1 = __importDefault(require("./point"));
28+
var C = point_1["default"];
29+
var p = new C(1, 2);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/point.d.ts ===
2+
declare class Point {
3+
>Point : Symbol(Point, Decl(point.d.ts, 0, 0))
4+
5+
x: number;
6+
>x : Symbol(Point.x, Decl(point.d.ts, 0, 21))
7+
8+
y: number;
9+
>y : Symbol(Point.y, Decl(point.d.ts, 1, 14))
10+
11+
constructor(x: number, y: number);
12+
>x : Symbol(x, Decl(point.d.ts, 4, 16))
13+
>y : Symbol(y, Decl(point.d.ts, 4, 26))
14+
15+
static default: "foo";
16+
>default : Symbol(Point.default, Decl(point.d.ts, 4, 38))
17+
}
18+
19+
export = Point;
20+
>Point : Symbol(Point, Decl(point.d.ts, 0, 0))
21+
22+
=== tests/cases/compiler/index.ts ===
23+
import Point from "./point";
24+
>Point : Symbol(Point, Decl(index.ts, 0, 6))
25+
26+
const C = Point;
27+
>C : Symbol(C, Decl(index.ts, 2, 5))
28+
>Point : Symbol(Point, Decl(index.ts, 0, 6))
29+
30+
const p = new C(1, 2);
31+
>p : Symbol(p, Decl(index.ts, 3, 5))
32+
>C : Symbol(C, Decl(index.ts, 2, 5))
33+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
=== tests/cases/compiler/point.d.ts ===
2+
declare class Point {
3+
>Point : Point
4+
5+
x: number;
6+
>x : number
7+
8+
y: number;
9+
>y : number
10+
11+
constructor(x: number, y: number);
12+
>x : number
13+
>y : number
14+
15+
static default: "foo";
16+
>default : "foo"
17+
}
18+
19+
export = Point;
20+
>Point : Point
21+
22+
=== tests/cases/compiler/index.ts ===
23+
import Point from "./point";
24+
>Point : typeof Point
25+
26+
const C = Point;
27+
>C : typeof Point
28+
>Point : typeof Point
29+
30+
const p = new C(1, 2);
31+
>p : Point
32+
>new C(1, 2) : Point
33+
>C : typeof Point
34+
>1 : 1
35+
>2 : 2
36+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @esModuleInterop: true
2+
// @filename: point.d.ts
3+
declare class Point {
4+
x: number;
5+
y: number;
6+
7+
constructor(x: number, y: number);
8+
9+
static default: "foo";
10+
}
11+
12+
export = Point;
13+
// @filename: index.ts
14+
import Point from "./point";
15+
16+
const C = Point;
17+
const p = new C(1, 2);

0 commit comments

Comments
 (0)