Skip to content

Commit 275c3e3

Browse files
committed
feat(29624): improve errors for non-exported types
1 parent 76ee021 commit 275c3e3

13 files changed

+181
-5
lines changed

src/compiler/checker.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -2355,7 +2355,7 @@ namespace ts {
23552355
);
23562356
}
23572357
else {
2358-
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
2358+
reportNoExportedMember(name, declarationName, moduleSymbol, moduleName);
23592359
}
23602360
}
23612361
}
@@ -2364,6 +2364,37 @@ namespace ts {
23642364
}
23652365
}
23662366

2367+
function reportNoExportedMember(name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void {
2368+
const locals = moduleSymbol.valueDeclaration.locals;
2369+
if (locals) {
2370+
const localDeclaration = locals.get(name.escapedText);
2371+
if (localDeclaration) {
2372+
const diagnostic = error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName);
2373+
addRelatedInfo(diagnostic,
2374+
createDiagnosticForNode(localDeclaration.valueDeclaration, Diagnostics._0_is_declared_here, symbolToString(localDeclaration))
2375+
);
2376+
}
2377+
else {
2378+
const suggestion = getSpellingSuggestionForName(idText(name), arrayFrom(locals.values()), SymbolFlags.ModuleMember);
2379+
if (suggestion) {
2380+
const suggestionName = symbolToString(suggestion);
2381+
const diagnostic = error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, suggestionName, declarationName);
2382+
if (suggestion.valueDeclaration) {
2383+
addRelatedInfo(diagnostic,
2384+
createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
2385+
);
2386+
}
2387+
}
2388+
else {
2389+
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
2390+
}
2391+
}
2392+
}
2393+
else {
2394+
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
2395+
}
2396+
}
2397+
23672398
function getTargetOfImportSpecifier(node: ImportSpecifier, dontResolveAlias: boolean): Symbol | undefined {
23682399
const resolved = getExternalModuleMember(node.parent.parent.parent, node, dontResolveAlias);
23692400
if (resolved && node.parent.parent.isTypeOnly) {

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,14 @@
17651765
"category": "Error",
17661766
"code": 2458
17671767
},
1768+
"Module '{0}' declares '{1}' locally, but it is not exported.": {
1769+
"category": "Error",
1770+
"code": 2459
1771+
},
1772+
"Module '{0}' declares '{1}' locally, but it is exported as '{2}'.": {
1773+
"category": "Error",
1774+
"code": 2460
1775+
},
17681776
"Type '{0}' is not an array type.": {
17691777
"category": "Error",
17701778
"code": 2461
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(1,10): error TS2305: Module '"./es6ImportNamedImportNoNamedExports_0"' has no exported member 'a'.
2-
tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(2,10): error TS2305: Module '"./es6ImportNamedImportNoNamedExports_0"' has no exported member 'a'.
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.
33

44

55
==== tests/cases/compiler/es6ImportNamedImportNoNamedExports_0.ts (0 errors) ====
@@ -9,7 +9,9 @@ tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts(2,10): error TS2305
99
==== tests/cases/compiler/es6ImportNamedImportNoNamedExports_1.ts (2 errors) ====
1010
import { a } from "./es6ImportNamedImportNoNamedExports_0";
1111
~
12-
!!! error TS2305: Module '"./es6ImportNamedImportNoNamedExports_0"' has no exported member 'a'.
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.
1314
import { a as x } from "./es6ImportNamedImportNoNamedExports_0";
1415
~
15-
!!! error TS2305: Module '"./es6ImportNamedImportNoNamedExports_0"' has no exported member 'a'.
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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/compiler/b.ts(1,10): error TS2460: Module '"./a"' declares 'assertNever' locally, but it is exported as 'assertNevar'.
2+
3+
4+
==== tests/cases/compiler/a.ts (0 errors) ====
5+
declare function assertNever(): void;
6+
declare function foo(): void;
7+
export { foo };
8+
9+
==== tests/cases/compiler/b.ts (1 errors) ====
10+
import { assertNevar } from "./a";
11+
~~~~~~~~~~~
12+
!!! error TS2460: Module '"./a"' declares 'assertNever' locally, but it is exported as 'assertNevar'.
13+
!!! related TS2728 tests/cases/compiler/a.ts:1:18: 'assertNever' is declared here.
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [tests/cases/compiler/exportLocalSpellingSuggestion.ts] ////
2+
3+
//// [a.ts]
4+
declare function assertNever(): void;
5+
declare function foo(): void;
6+
export { foo };
7+
8+
//// [b.ts]
9+
import { assertNevar } from "./a";
10+
11+
12+
//// [a.js]
13+
"use strict";
14+
exports.__esModule = true;
15+
//// [b.js]
16+
"use strict";
17+
exports.__esModule = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/a.ts ===
2+
declare function assertNever(): void;
3+
>assertNever : Symbol(assertNever, Decl(a.ts, 0, 0))
4+
5+
declare function foo(): void;
6+
>foo : Symbol(foo, Decl(a.ts, 0, 37))
7+
8+
export { foo };
9+
>foo : Symbol(foo, Decl(a.ts, 2, 8))
10+
11+
=== tests/cases/compiler/b.ts ===
12+
import { assertNevar } from "./a";
13+
>assertNevar : Symbol(assertNevar, Decl(b.ts, 0, 8))
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/a.ts ===
2+
declare function assertNever(): void;
3+
>assertNever : () => void
4+
5+
declare function foo(): void;
6+
>foo : () => void
7+
8+
export { foo };
9+
>foo : () => void
10+
11+
=== tests/cases/compiler/b.ts ===
12+
import { assertNevar } from "./a";
13+
>assertNevar : any
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tests/cases/compiler/b.ts(1,10): error TS2459: Module '"./a"' declares 'foo' locally, but it is not exported.
2+
3+
4+
==== tests/cases/compiler/a.ts (0 errors) ====
5+
declare function foo(): any
6+
declare function bar(): any;
7+
8+
export { bar };
9+
10+
==== tests/cases/compiler/b.ts (1 errors) ====
11+
import { foo } from "./a";
12+
~~~
13+
!!! error TS2459: Module '"./a"' declares 'foo' locally, but it is not exported.
14+
!!! related TS2728 tests/cases/compiler/a.ts:1:18: 'foo' is declared here.
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [tests/cases/compiler/exportLocalSuggestion.ts] ////
2+
3+
//// [a.ts]
4+
declare function foo(): any
5+
declare function bar(): any;
6+
7+
export { bar };
8+
9+
//// [b.ts]
10+
import { foo } from "./a";
11+
12+
13+
//// [a.js]
14+
"use strict";
15+
exports.__esModule = true;
16+
//// [b.js]
17+
"use strict";
18+
exports.__esModule = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/a.ts ===
2+
declare function foo(): any
3+
>foo : Symbol(foo, Decl(a.ts, 0, 0))
4+
5+
declare function bar(): any;
6+
>bar : Symbol(bar, Decl(a.ts, 0, 27))
7+
8+
export { bar };
9+
>bar : Symbol(bar, Decl(a.ts, 3, 8))
10+
11+
=== tests/cases/compiler/b.ts ===
12+
import { foo } from "./a";
13+
>foo : Symbol(foo, Decl(b.ts, 0, 8))
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/a.ts ===
2+
declare function foo(): any
3+
>foo : () => any
4+
5+
declare function bar(): any;
6+
>bar : () => any
7+
8+
export { bar };
9+
>bar : () => any
10+
11+
=== tests/cases/compiler/b.ts ===
12+
import { foo } from "./a";
13+
>foo : any
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @filename: a.ts
2+
declare function assertNever(): void;
3+
declare function foo(): void;
4+
export { foo };
5+
6+
// @filename: b.ts
7+
import { assertNevar } from "./a";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @filename: a.ts
2+
declare function foo(): any
3+
declare function bar(): any;
4+
5+
export { bar };
6+
7+
// @filename: b.ts
8+
import { foo } from "./a";

0 commit comments

Comments
 (0)