Skip to content

Commit 1273b68

Browse files
committed
fix(36909): wrong error message when trying to named-import an export
1 parent 7f1df6e commit 1273b68

39 files changed

+520
-18
lines changed

src/compiler/checker.ts

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,7 +2538,7 @@ namespace ts {
25382538
);
25392539
}
25402540
else {
2541-
reportNonExportedMember(name, declarationName, moduleSymbol, moduleName);
2541+
reportNonExportedMember(node, name, declarationName, moduleSymbol, moduleName);
25422542
}
25432543
}
25442544
}
@@ -2547,27 +2547,50 @@ namespace ts {
25472547
}
25482548
}
25492549

2550-
function reportNonExportedMember(name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
2550+
function reportNonExportedMember(node: ImportDeclaration | ExportDeclaration, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
25512551
const localSymbol = moduleSymbol.valueDeclaration.locals?.get(name.escapedText);
25522552
const exports = moduleSymbol.exports;
2553-
25542553
if (localSymbol) {
2555-
const exportedSymbol = exports && !exports.has(InternalSymbolName.ExportEquals)
2556-
? find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol))
2557-
: undefined;
2558-
const diagnostic = exportedSymbol
2559-
? error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol))
2560-
: error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName);
2554+
const exportedEqualsSymbol = exports?.get(InternalSymbolName.ExportEquals);
2555+
if (exportedEqualsSymbol) {
2556+
getSymbolIfSameReference(exportedEqualsSymbol, localSymbol) ? reportInvalidImportEqualsExportMember(node, name, declarationName, moduleName) :
2557+
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
2558+
}
2559+
else {
2560+
const exportedSymbol = exports ? find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol)) : undefined;
2561+
const diagnostic = exportedSymbol ? error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol)) :
2562+
error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName);
25612563

2562-
addRelatedInfo(diagnostic,
2563-
...map(localSymbol.declarations, (decl, index) =>
2564-
createDiagnosticForNode(decl, index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, declarationName)));
2564+
addRelatedInfo(diagnostic,
2565+
...map(localSymbol.declarations, (decl, index) =>
2566+
createDiagnosticForNode(decl, index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, declarationName)));
2567+
}
25652568
}
25662569
else {
25672570
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
25682571
}
25692572
}
25702573

2574+
function reportInvalidImportEqualsExportMember(node: ImportDeclaration | ExportDeclaration, name: Identifier, declarationName: string, moduleName: string) {
2575+
if (moduleKind >= ModuleKind.ES2015) {
2576+
const message = compilerOptions.esModuleInterop ? Diagnostics._0_can_only_be_imported_by_using_a_default_import :
2577+
Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
2578+
error(name, message, declarationName);
2579+
}
2580+
else {
2581+
if (isInJSFile(node)) {
2582+
const message = compilerOptions.esModuleInterop ? Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import :
2583+
Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
2584+
error(name, message, declarationName);
2585+
}
2586+
else {
2587+
const message = compilerOptions.esModuleInterop ? Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import :
2588+
Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import;
2589+
error(name, message, declarationName, declarationName, moduleName);
2590+
}
2591+
}
2592+
}
2593+
25712594
function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol | undefined {
25722595
const resolved = getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias);
25732596
markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);

src/compiler/diagnosticMessages.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,22 @@
23172317
"category": "Error",
23182318
"code": 2594
23192319
},
2320+
"'{0}' can only be imported by using a default import.": {
2321+
"category": "Error",
2322+
"code": 2595
2323+
},
2324+
"'{0}' can only be imported by turning on the 'esModuleInterop' flag and using a default import.": {
2325+
"category": "Error",
2326+
"code": 2596
2327+
},
2328+
"'{0}' can only be imported by using a 'require' call or by using a default import.": {
2329+
"category": "Error",
2330+
"code": 2597
2331+
},
2332+
"'{0}' can only be imported by using a 'require' call or by turning on the 'esModuleInterop' flag and using a default import.": {
2333+
"category": "Error",
2334+
"code": 2598
2335+
},
23202336
"JSX element attributes type '{0}' may not be a union type.": {
23212337
"category": "Error",
23222338
"code": 2600
@@ -2381,6 +2397,14 @@
23812397
"category": "Error",
23822398
"code": 2615
23832399
},
2400+
"'{0}' can only be imported by using 'import {1} = require({2})' or a default import.": {
2401+
"category": "Error",
2402+
"code": 2616
2403+
},
2404+
"'{0}' can only be imported by using 'import {1} = require({2})' or by turning on the 'esModuleInterop' flag and using a default import.": {
2405+
"category": "Error",
2406+
"code": 2617
2407+
},
23842408

23852409
"Cannot augment module '{0}' with value exports because it resolves to a non-module entity.": {
23862410
"category": "Error",
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(1,10): error TS2459: Module '"./es6ImportNamedImportNoNamedExports_0"' declares 'a' locally, but it is not exported.
2-
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(2,10): error TS2459: Module '"./es6ImportNamedImportNoNamedExports_0"' declares 'a' locally, but it is not exported.
1+
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(1,10): error TS2617: 'a' can only be imported by using 'import a = require("./es6ImportNamedImportNoNamedExports_0")' or by turning on the 'esModuleInterop' flag and using a default import.
2+
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(2,10): error TS2617: 'a' can only be imported by using 'import a = require("./es6ImportNamedImportNoNamedExports_0")' or by turning on the 'esModuleInterop' flag and using a default import.
33

44

55
==== tests/cases/compiler/es6ImportNamedImportNoNamedExports_0.ts (0 errors) ====
@@ -9,9 +9,7 @@ tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(2,10): error TS2459
99
==== tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts (2 errors) ====
1010
import { a } from "./es6ImportNamedImportNoNamedExports_0";
1111
~
12-
!!! error TS2459: Module '"./es6ImportNamedImportNoNamedExports_0"' declares 'a' locally, but it is not exported.
13-
!!! related TS2728 tests/cases/compiler/es6ImportNamedImportNoNamedExports_0.ts:1:5: 'a' is declared here.
12+
!!! error TS2617: 'a' can only be imported by using 'import a = require("./es6ImportNamedImportNoNamedExports_0")' or by turning on the 'esModuleInterop' flag and using a default import.
1413
import { a as x } from "./es6ImportNamedImportNoNamedExports_0";
1514
~
16-
!!! error TS2459: Module '"./es6ImportNamedImportNoNamedExports_0"' declares 'a' locally, but it is not exported.
17-
!!! related TS2728 tests/cases/compiler/es6ImportNamedImportNoNamedExports_0.ts:1:5: 'a' is declared here.
15+
!!! error TS2617: 'a' can only be imported by using 'import a = require("./es6ImportNamedImportNoNamedExports_0")' or by turning on the 'esModuleInterop' flag and using a default import.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
2+
tests/cases/compiler/b.js(1,10): error TS2596: 'Foo' can only be imported by turning on the 'esModuleInterop' flag and using a default import.
3+
tests/cases/compiler/b.js(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
4+
5+
6+
==== tests/cases/compiler/a.ts (1 errors) ====
7+
class Foo {}
8+
export = Foo;
9+
~~~~~~~~~~~~~
10+
!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
11+
12+
==== tests/cases/compiler/b.js (2 errors) ====
13+
import { Foo } from './a';
14+
~~~
15+
!!! error TS2596: 'Foo' can only be imported by turning on the 'esModuleInterop' flag and using a default import.
16+
~~~~~
17+
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
4+
5+
export = Foo;
6+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
7+
8+
=== tests/cases/compiler/b.js ===
9+
import { Foo } from './a';
10+
>Foo : Symbol(Foo, Decl(b.js, 0, 8))
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Foo
4+
5+
export = Foo;
6+
>Foo : Foo
7+
8+
=== tests/cases/compiler/b.js ===
9+
import { Foo } from './a';
10+
>Foo : any
11+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
2+
tests/cases/compiler/b.js(1,10): error TS2595: 'Foo' can only be imported by using a default import.
3+
tests/cases/compiler/b.js(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
4+
5+
6+
==== tests/cases/compiler/a.ts (1 errors) ====
7+
class Foo {}
8+
export = Foo;
9+
~~~~~~~~~~~~~
10+
!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
11+
12+
==== tests/cases/compiler/b.js (2 errors) ====
13+
import { Foo } from './a';
14+
~~~
15+
!!! error TS2595: 'Foo' can only be imported by using a default import.
16+
~~~~~
17+
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
4+
5+
export = Foo;
6+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
7+
8+
=== tests/cases/compiler/b.js ===
9+
import { Foo } from './a';
10+
>Foo : Symbol(Foo, Decl(b.js, 0, 8))
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Foo
4+
5+
export = Foo;
6+
>Foo : Foo
7+
8+
=== tests/cases/compiler/b.js ===
9+
import { Foo } from './a';
10+
>Foo : any
11+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/compiler/b.ts(1,10): error TS2617: 'Foo' can only be imported by using 'import Foo = require("./a")' or by turning on the 'esModuleInterop' flag and using a default import.
2+
tests/cases/compiler/b.ts(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
3+
4+
5+
==== tests/cases/compiler/a.ts (0 errors) ====
6+
class Foo {}
7+
export = Foo;
8+
9+
==== tests/cases/compiler/b.ts (2 errors) ====
10+
import { Foo } from './a';
11+
~~~
12+
!!! error TS2617: 'Foo' can only be imported by using 'import Foo = require("./a")' or by turning on the 'esModuleInterop' flag and using a default import.
13+
~~~~~
14+
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// [tests/cases/compiler/importNonExportedMember4.ts] ////
2+
3+
//// [a.ts]
4+
class Foo {}
5+
export = Foo;
6+
7+
//// [b.ts]
8+
import { Foo } from './a';
9+
10+
//// [a.js]
11+
"use strict";
12+
var Foo = /** @class */ (function () {
13+
function Foo() {
14+
}
15+
return Foo;
16+
}());
17+
module.exports = Foo;
18+
//// [b.js]
19+
"use strict";
20+
exports.__esModule = true;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
4+
5+
export = Foo;
6+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : Symbol(Foo, Decl(b.ts, 0, 8))
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Foo
4+
5+
export = Foo;
6+
>Foo : Foo
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : any
11+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/compiler/b.ts(1,10): error TS2616: 'Foo' can only be imported by using 'import Foo = require("./a")' or a default import.
2+
tests/cases/compiler/b.ts(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
3+
4+
5+
==== tests/cases/compiler/a.ts (0 errors) ====
6+
class Foo {}
7+
export = Foo;
8+
9+
==== tests/cases/compiler/b.ts (2 errors) ====
10+
import { Foo } from './a';
11+
~~~
12+
!!! error TS2616: 'Foo' can only be imported by using 'import Foo = require("./a")' or a default import.
13+
~~~~~
14+
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// [tests/cases/compiler/importNonExportedMember5.ts] ////
2+
3+
//// [a.ts]
4+
class Foo {}
5+
export = Foo;
6+
7+
//// [b.ts]
8+
import { Foo } from './a';
9+
10+
//// [a.js]
11+
"use strict";
12+
var Foo = /** @class */ (function () {
13+
function Foo() {
14+
}
15+
return Foo;
16+
}());
17+
module.exports = Foo;
18+
//// [b.js]
19+
"use strict";
20+
exports.__esModule = true;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
4+
5+
export = Foo;
6+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : Symbol(Foo, Decl(b.ts, 0, 8))
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Foo
4+
5+
export = Foo;
6+
>Foo : Foo
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : any
11+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
2+
tests/cases/compiler/b.ts(1,10): error TS2596: 'Foo' can only be imported by turning on the 'esModuleInterop' flag and using a default import.
3+
tests/cases/compiler/b.ts(1,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
4+
5+
6+
==== tests/cases/compiler/a.ts (1 errors) ====
7+
class Foo {}
8+
export = Foo;
9+
~~~~~~~~~~~~~
10+
!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead.
11+
12+
==== tests/cases/compiler/b.ts (2 errors) ====
13+
import { Foo } from './a';
14+
~~~
15+
!!! error TS2596: 'Foo' can only be imported by turning on the 'esModuleInterop' flag and using a default import.
16+
~~~~~
17+
!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [tests/cases/compiler/importNonExportedMember6.ts] ////
2+
3+
//// [a.ts]
4+
class Foo {}
5+
export = Foo;
6+
7+
//// [b.ts]
8+
import { Foo } from './a';
9+
10+
//// [a.js]
11+
var Foo = /** @class */ (function () {
12+
function Foo() {
13+
}
14+
return Foo;
15+
}());
16+
//// [b.js]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
4+
5+
export = Foo;
6+
>Foo : Symbol(Foo, Decl(a.ts, 0, 0))
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : Symbol(Foo, Decl(b.ts, 0, 8))
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class Foo {}
3+
>Foo : Foo
4+
5+
export = Foo;
6+
>Foo : Foo
7+
8+
=== tests/cases/compiler/b.ts ===
9+
import { Foo } from './a';
10+
>Foo : any
11+

0 commit comments

Comments
 (0)