Skip to content

Commit 039e85a

Browse files
Merge pull request #17459 from Microsoft/errorForPropertyOfTypeAsType
Improve error message to suggest indexed access types.
2 parents 12acc14 + 7c7f9ad commit 039e85a

File tree

5 files changed

+177
-0
lines changed

5 files changed

+177
-0
lines changed

src/compiler/checker.ts

+15
Original file line numberDiff line numberDiff line change
@@ -1240,7 +1240,22 @@ namespace ts {
12401240
function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
12411241
if (meaning === SymbolFlags.Namespace) {
12421242
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined));
1243+
const parent = errorLocation.parent;
12431244
if (symbol) {
1245+
if (isQualifiedName(parent)) {
1246+
Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace");
1247+
const propName = parent.right.escapedText;
1248+
const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName);
1249+
if (propType) {
1250+
error(
1251+
parent,
1252+
Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1,
1253+
unescapeLeadingUnderscores(name),
1254+
unescapeLeadingUnderscores(propName),
1255+
);
1256+
return true;
1257+
}
1258+
}
12441259
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name));
12451260
return true;
12461261
}

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -2192,6 +2192,10 @@
21922192
"category": "Error",
21932193
"code": 2712
21942194
},
2195+
"Cannot access '{0}.{1}' because '{0}' is a type, but not a namespace. Did you mean to retrieve the type of the property '{1}' in '{0}' with '{0}[\"{1}\"]'?": {
2196+
"category": "Error",
2197+
"code": 2713
2198+
},
21952199

21962200
"Import declaration '{0}' is using private name '{1}'.": {
21972201
"category": "Error",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(6,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
2+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(14,12): error TS2503: Cannot find namespace 'Foo'.
3+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(22,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
4+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(29,12): error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
5+
tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here.
6+
7+
8+
==== tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts (5 errors) ====
9+
namespace Test1 {
10+
export interface Foo {
11+
bar: string;
12+
}
13+
14+
var x: Foo.bar = "";
15+
~~~~~~~
16+
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
17+
}
18+
19+
namespace Test2 {
20+
export class Foo {
21+
bar: string;
22+
}
23+
24+
var x: Foo.bar = "";
25+
~~~
26+
!!! error TS2503: Cannot find namespace 'Foo'.
27+
}
28+
29+
namespace Test3 {
30+
export type Foo = {
31+
bar: string;
32+
}
33+
34+
var x: Foo.bar = "";
35+
~~~~~~~
36+
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
37+
}
38+
39+
namespace Test4 {
40+
export type Foo = { bar: number }
41+
| { bar: string }
42+
43+
var x: Foo.bar = "";
44+
~~~~~~~
45+
!!! error TS2713: Cannot access 'Foo.bar' because 'Foo' is a type, but not a namespace. Did you mean to retrieve the type of the property 'bar' in 'Foo' with 'Foo["bar"]'?
46+
}
47+
48+
namespace Test5 {
49+
export type Foo = { bar: number }
50+
| { wat: string }
51+
52+
var x: Foo.bar = "";
53+
~~~
54+
!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here.
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//// [errorForUsingPropertyOfTypeAsType01.ts]
2+
namespace Test1 {
3+
export interface Foo {
4+
bar: string;
5+
}
6+
7+
var x: Foo.bar = "";
8+
}
9+
10+
namespace Test2 {
11+
export class Foo {
12+
bar: string;
13+
}
14+
15+
var x: Foo.bar = "";
16+
}
17+
18+
namespace Test3 {
19+
export type Foo = {
20+
bar: string;
21+
}
22+
23+
var x: Foo.bar = "";
24+
}
25+
26+
namespace Test4 {
27+
export type Foo = { bar: number }
28+
| { bar: string }
29+
30+
var x: Foo.bar = "";
31+
}
32+
33+
namespace Test5 {
34+
export type Foo = { bar: number }
35+
| { wat: string }
36+
37+
var x: Foo.bar = "";
38+
}
39+
40+
//// [errorForUsingPropertyOfTypeAsType01.js]
41+
var Test1;
42+
(function (Test1) {
43+
var x = "";
44+
})(Test1 || (Test1 = {}));
45+
var Test2;
46+
(function (Test2) {
47+
var Foo = (function () {
48+
function Foo() {
49+
}
50+
return Foo;
51+
}());
52+
Test2.Foo = Foo;
53+
var x = "";
54+
})(Test2 || (Test2 = {}));
55+
var Test3;
56+
(function (Test3) {
57+
var x = "";
58+
})(Test3 || (Test3 = {}));
59+
var Test4;
60+
(function (Test4) {
61+
var x = "";
62+
})(Test4 || (Test4 = {}));
63+
var Test5;
64+
(function (Test5) {
65+
var x = "";
66+
})(Test5 || (Test5 = {}));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace Test1 {
2+
export interface Foo {
3+
bar: string;
4+
}
5+
6+
var x: Foo.bar = "";
7+
}
8+
9+
namespace Test2 {
10+
export class Foo {
11+
bar: string;
12+
}
13+
14+
var x: Foo.bar = "";
15+
}
16+
17+
namespace Test3 {
18+
export type Foo = {
19+
bar: string;
20+
}
21+
22+
var x: Foo.bar = "";
23+
}
24+
25+
namespace Test4 {
26+
export type Foo = { bar: number }
27+
| { bar: string }
28+
29+
var x: Foo.bar = "";
30+
}
31+
32+
namespace Test5 {
33+
export type Foo = { bar: number }
34+
| { wat: string }
35+
36+
var x: Foo.bar = "";
37+
}

0 commit comments

Comments
 (0)