Skip to content

Commit 13280de

Browse files
weswighamtypescript-bot
authored andcommitted
Cherry-pick PR microsoft#49814 into release-4.8
Component commits: e2d22fa Unify default import resolution across specifier target codepaths b341699 Merge main into branch cf010b5 Use differing type aliases, per request
1 parent 565a444 commit 13280de

15 files changed

+1348
-62
lines changed

src/compiler/checker.ts

Lines changed: 102 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,44 +2798,66 @@ namespace ts {
27982798
function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined {
27992799
const moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier);
28002800
if (moduleSymbol) {
2801-
let exportDefaultSymbol: Symbol | undefined;
2802-
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
2803-
exportDefaultSymbol = moduleSymbol;
2804-
}
2805-
else {
2806-
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias);
2807-
}
2808-
2809-
const file = moduleSymbol.declarations?.find(isSourceFile);
2810-
const hasDefaultOnly = isOnlyImportedAsDefault(node.parent.moduleSpecifier);
2811-
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, node.parent.moduleSpecifier);
2812-
if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) {
2813-
if (hasExportAssignmentSymbol(moduleSymbol)) {
2814-
const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop";
2815-
const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals);
2816-
const exportAssignment = exportEqualsSymbol!.valueDeclaration;
2817-
const err = error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName);
2818-
2819-
if (exportAssignment) {
2820-
addRelatedInfo(err, createDiagnosticForNode(
2821-
exportAssignment,
2822-
Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag,
2823-
compilerOptionName
2824-
));
2825-
}
2826-
}
2827-
else {
2828-
reportNonDefaultExport(moduleSymbol, node);
2801+
return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias);
2802+
}
2803+
}
2804+
2805+
function getTargetofModuleDefault(moduleSymbol: Symbol, node: ImportClause | ImportOrExportSpecifier, dontResolveAlias: boolean) {
2806+
let exportDefaultSymbol: Symbol | undefined;
2807+
if (isShorthandAmbientModuleSymbol(moduleSymbol)) {
2808+
exportDefaultSymbol = moduleSymbol;
2809+
}
2810+
else {
2811+
exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias);
2812+
}
2813+
2814+
const file = moduleSymbol.declarations?.find(isSourceFile);
2815+
const specifier = getModuleSpecifierForImportOrExport(node);
2816+
if (!specifier) {
2817+
return exportDefaultSymbol;
2818+
}
2819+
const hasDefaultOnly = isOnlyImportedAsDefault(specifier);
2820+
const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier);
2821+
if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) {
2822+
if (hasExportAssignmentSymbol(moduleSymbol)) {
2823+
const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop";
2824+
const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals);
2825+
const exportAssignment = exportEqualsSymbol!.valueDeclaration;
2826+
const err = error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName);
2827+
2828+
if (exportAssignment) {
2829+
addRelatedInfo(err, createDiagnosticForNode(
2830+
exportAssignment,
2831+
Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag,
2832+
compilerOptionName
2833+
));
28292834
}
28302835
}
2831-
else if (hasSyntheticDefault || hasDefaultOnly) {
2832-
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
2833-
const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
2834-
markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteTypeOnly*/ false);
2835-
return resolved;
2836+
else if (isImportClause(node)) {
2837+
reportNonDefaultExport(moduleSymbol, node);
28362838
}
2837-
markSymbolOfAliasDeclarationIfTypeOnly(node, exportDefaultSymbol, /*finalTarget*/ undefined, /*overwriteTypeOnly*/ false);
2838-
return exportDefaultSymbol;
2839+
else {
2840+
errorNoModuleMemberSymbol(moduleSymbol, moduleSymbol, node, isImportOrExportSpecifier(node) && node.propertyName || node.name);
2841+
}
2842+
}
2843+
else if (hasSyntheticDefault || hasDefaultOnly) {
2844+
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
2845+
const resolved = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
2846+
markSymbolOfAliasDeclarationIfTypeOnly(node, moduleSymbol, resolved, /*overwriteTypeOnly*/ false);
2847+
return resolved;
2848+
}
2849+
markSymbolOfAliasDeclarationIfTypeOnly(node, exportDefaultSymbol, /*finalTarget*/ undefined, /*overwriteTypeOnly*/ false);
2850+
return exportDefaultSymbol;
2851+
}
2852+
2853+
function getModuleSpecifierForImportOrExport(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportOrExportSpecifier): Expression | undefined {
2854+
switch (node.kind) {
2855+
case SyntaxKind.ImportClause: return node.parent.moduleSpecifier;
2856+
case SyntaxKind.ImportEqualsDeclaration: return isExternalModuleReference(node.moduleReference) ? node.moduleReference.expression : undefined;
2857+
case SyntaxKind.NamespaceImport: return node.parent.parent.moduleSpecifier;
2858+
case SyntaxKind.ImportSpecifier: return node.parent.parent.parent.moduleSpecifier;
2859+
case SyntaxKind.ExportSpecifier: return node.parent.parent.moduleSpecifier;
2860+
default: return Debug.assertNever(node);
28392861
}
28402862
}
28412863

@@ -2969,38 +2991,42 @@ namespace ts {
29692991
combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) :
29702992
symbolFromModule || symbolFromVariable;
29712993
if (!symbol) {
2972-
const moduleName = getFullyQualifiedName(moduleSymbol, node);
2973-
const declarationName = declarationNameToString(name);
2974-
const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol);
2975-
if (suggestion !== undefined) {
2976-
const suggestionName = symbolToString(suggestion);
2977-
const diagnostic = error(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName);
2978-
if (suggestion.valueDeclaration) {
2979-
addRelatedInfo(diagnostic,
2980-
createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
2981-
);
2982-
}
2983-
}
2984-
else {
2985-
if (moduleSymbol.exports?.has(InternalSymbolName.Default)) {
2986-
error(
2987-
name,
2988-
Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_to_use_import_1_from_0_instead,
2989-
moduleName,
2990-
declarationName
2991-
);
2992-
}
2993-
else {
2994-
reportNonExportedMember(node, name, declarationName, moduleSymbol, moduleName);
2995-
}
2996-
}
2994+
errorNoModuleMemberSymbol(moduleSymbol, targetSymbol, node, name);
29972995
}
29982996
return symbol;
29992997
}
30002998
}
30012999
}
30023000

3003-
function reportNonExportedMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
3001+
function errorNoModuleMemberSymbol(moduleSymbol: Symbol, targetSymbol: Symbol, node: Node, name: Identifier) {
3002+
const moduleName = getFullyQualifiedName(moduleSymbol, node);
3003+
const declarationName = declarationNameToString(name);
3004+
const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol);
3005+
if (suggestion !== undefined) {
3006+
const suggestionName = symbolToString(suggestion);
3007+
const diagnostic = error(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName);
3008+
if (suggestion.valueDeclaration) {
3009+
addRelatedInfo(diagnostic,
3010+
createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
3011+
);
3012+
}
3013+
}
3014+
else {
3015+
if (moduleSymbol.exports?.has(InternalSymbolName.Default)) {
3016+
error(
3017+
name,
3018+
Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_to_use_import_1_from_0_instead,
3019+
moduleName,
3020+
declarationName
3021+
);
3022+
}
3023+
else {
3024+
reportNonExportedMember(node, name, declarationName, moduleSymbol, moduleName);
3025+
}
3026+
}
3027+
}
3028+
3029+
function reportNonExportedMember(node: Node, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
30043030
const localSymbol = moduleSymbol.valueDeclaration?.locals?.get(name.escapedText);
30053031
const exports = moduleSymbol.exports;
30063032
if (localSymbol) {
@@ -3025,7 +3051,7 @@ namespace ts {
30253051
}
30263052
}
30273053

3028-
function reportInvalidImportEqualsExportMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, name: Identifier, declarationName: string, moduleName: string) {
3054+
function reportInvalidImportEqualsExportMember(node: Node, name: Identifier, declarationName: string, moduleName: string) {
30293055
if (moduleKind >= ModuleKind.ES2015) {
30303056
const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_default_import :
30313057
Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
@@ -3046,6 +3072,13 @@ namespace ts {
30463072
}
30473073

30483074
function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined {
3075+
if (isImportSpecifier(node) && idText(node.propertyName || node.name) === InternalSymbolName.Default) {
3076+
const specifier = getModuleSpecifierForImportOrExport(node);
3077+
const moduleSymbol = specifier && resolveExternalModuleName(node, specifier);
3078+
if (moduleSymbol) {
3079+
return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias);
3080+
}
3081+
}
30493082
const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent;
30503083
const commonJSPropertyAccess = getCommonJSPropertyAccess(root);
30513084
const resolved = getExternalModuleMember(root, commonJSPropertyAccess || node, dontResolveAlias);
@@ -3070,6 +3103,13 @@ namespace ts {
30703103
}
30713104

30723105
function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) {
3106+
if (idText(node.propertyName || node.name) === InternalSymbolName.Default) {
3107+
const specifier = getModuleSpecifierForImportOrExport(node);
3108+
const moduleSymbol = specifier && resolveExternalModuleName(node, specifier);
3109+
if (moduleSymbol) {
3110+
return getTargetofModuleDefault(moduleSymbol, node, !!dontResolveAlias);
3111+
}
3112+
}
30733113
const resolved = node.parent.parent.moduleSpecifier ?
30743114
getExternalModuleMember(node.parent.parent, node, dontResolveAlias) :
30753115
resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias);
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
tests/cases/compiler/b.ts(15,1): error TS2349: This expression is not callable.
2+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
3+
tests/cases/compiler/b.ts(16,1): error TS2349: This expression is not callable.
4+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
5+
tests/cases/compiler/b.ts(17,1): error TS2349: This expression is not callable.
6+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
7+
tests/cases/compiler/b.ts(18,1): error TS2349: This expression is not callable.
8+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
9+
tests/cases/compiler/b.ts(19,6): error TS2349: This expression is not callable.
10+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
11+
tests/cases/compiler/b.ts(20,6): error TS2349: This expression is not callable.
12+
Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
13+
14+
15+
==== tests/cases/compiler/mod.ts (0 errors) ====
16+
declare function fun(): void;
17+
export default fun;
18+
==== tests/cases/compiler/a.ts (0 errors) ====
19+
import mod = require("./mod");
20+
export = mod;
21+
==== tests/cases/compiler/b.ts (6 errors) ====
22+
import a from "./a";
23+
import { default as b } from "./a";
24+
import c, { default as d } from "./a";
25+
import * as self from "./b";
26+
export { default } from "./a";
27+
export { default as def } from "./a";
28+
29+
a === b;
30+
b === c;
31+
c === d;
32+
d === self.default;
33+
self.default === self.def;
34+
35+
// should all fail
36+
a();
37+
~
38+
!!! error TS2349: This expression is not callable.
39+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
40+
b();
41+
~
42+
!!! error TS2349: This expression is not callable.
43+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
44+
c();
45+
~
46+
!!! error TS2349: This expression is not callable.
47+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
48+
d();
49+
~
50+
!!! error TS2349: This expression is not callable.
51+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
52+
self.default();
53+
~~~~~~~
54+
!!! error TS2349: This expression is not callable.
55+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
56+
self.def();
57+
~~~
58+
!!! error TS2349: This expression is not callable.
59+
!!! error TS2349: Type 'typeof import("tests/cases/compiler/mod")' has no call signatures.
60+
61+
// should all work
62+
a.default();
63+
b.default();
64+
c.default();
65+
d.default();
66+
self.default.default();
67+
self.def.default();
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//// [tests/cases/compiler/esModuleInteropDefaultImports.ts] ////
2+
3+
//// [mod.ts]
4+
declare function fun(): void;
5+
export default fun;
6+
//// [a.ts]
7+
import mod = require("./mod");
8+
export = mod;
9+
//// [b.ts]
10+
import a from "./a";
11+
import { default as b } from "./a";
12+
import c, { default as d } from "./a";
13+
import * as self from "./b";
14+
export { default } from "./a";
15+
export { default as def } from "./a";
16+
17+
a === b;
18+
b === c;
19+
c === d;
20+
d === self.default;
21+
self.default === self.def;
22+
23+
// should all fail
24+
a();
25+
b();
26+
c();
27+
d();
28+
self.default();
29+
self.def();
30+
31+
// should all work
32+
a.default();
33+
b.default();
34+
c.default();
35+
d.default();
36+
self.default.default();
37+
self.def.default();
38+
39+
//// [mod.js]
40+
"use strict";
41+
exports.__esModule = true;
42+
exports["default"] = fun;
43+
//// [a.js]
44+
"use strict";
45+
var mod = require("./mod");
46+
module.exports = mod;
47+
//// [b.js]
48+
"use strict";
49+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
50+
if (k2 === undefined) k2 = k;
51+
var desc = Object.getOwnPropertyDescriptor(m, k);
52+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
53+
desc = { enumerable: true, get: function() { return m[k]; } };
54+
}
55+
Object.defineProperty(o, k2, desc);
56+
}) : (function(o, m, k, k2) {
57+
if (k2 === undefined) k2 = k;
58+
o[k2] = m[k];
59+
}));
60+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
61+
Object.defineProperty(o, "default", { enumerable: true, value: v });
62+
}) : function(o, v) {
63+
o["default"] = v;
64+
});
65+
var __importStar = (this && this.__importStar) || function (mod) {
66+
if (mod && mod.__esModule) return mod;
67+
var result = {};
68+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
69+
__setModuleDefault(result, mod);
70+
return result;
71+
};
72+
var __importDefault = (this && this.__importDefault) || function (mod) {
73+
return (mod && mod.__esModule) ? mod : { "default": mod };
74+
};
75+
exports.__esModule = true;
76+
exports.def = exports["default"] = void 0;
77+
var a_1 = __importDefault(require("./a"));
78+
var a_2 = __importDefault(require("./a"));
79+
var a_3 = __importDefault(require("./a"));
80+
var self = __importStar(require("./b"));
81+
var a_4 = require("./a");
82+
__createBinding(exports, a_4, "default");
83+
var a_5 = require("./a");
84+
__createBinding(exports, a_5, "default", "def");
85+
a_1["default"] === a_2["default"];
86+
a_2["default"] === a_3["default"];
87+
a_3["default"] === a_3["default"];
88+
a_3["default"] === self["default"];
89+
self["default"] === self.def;
90+
// should all fail
91+
(0, a_1["default"])();
92+
(0, a_2["default"])();
93+
(0, a_3["default"])();
94+
(0, a_3["default"])();
95+
self["default"]();
96+
self.def();
97+
// should all work
98+
a_1["default"]["default"]();
99+
a_2["default"]["default"]();
100+
a_3["default"]["default"]();
101+
a_3["default"]["default"]();
102+
self["default"]["default"]();
103+
self.def["default"]();

0 commit comments

Comments
 (0)