From c14ff00bcfd35678613b056d2c7c17696db9c4ba Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 27 Jul 2017 11:22:12 -0700 Subject: [PATCH 1/5] Added test case. --- .../errorForUsingPropertyOfTypeAsType01.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts diff --git a/tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts b/tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts new file mode 100644 index 0000000000000..c20102881eae0 --- /dev/null +++ b/tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts @@ -0,0 +1,37 @@ +namespace Test1 { + export interface Foo { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test2 { + export class Foo { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test3 { + export type Foo = { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test4 { + export type Foo = { bar: number } + | { bar: string } + + var x: Foo.bar = ""; +} + +namespace Test5 { + export type Foo = { bar: number } + | { wat: string } + + var x: Foo.bar = ""; +} \ No newline at end of file From 677cc66e0327e2eaf6d9a729021f9dead467da50 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 27 Jul 2017 11:39:07 -0700 Subject: [PATCH 2/5] Accepted baselines. --- ...rForUsingPropertyOfTypeAsType01.errors.txt | 55 ++++++++++++++++ .../errorForUsingPropertyOfTypeAsType01.js | 66 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt create mode 100644 tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.js diff --git a/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt new file mode 100644 index 0000000000000..3285fe6a1d631 --- /dev/null +++ b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt @@ -0,0 +1,55 @@ +tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(6,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. +tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(14,12): error TS2503: Cannot find namespace 'Foo'. +tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(22,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. +tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(29,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. +tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + + +==== tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts (5 errors) ==== + namespace Test1 { + export interface Foo { + bar: string; + } + + var x: Foo.bar = ""; + ~~~ +!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + } + + namespace Test2 { + export class Foo { + bar: string; + } + + var x: Foo.bar = ""; + ~~~ +!!! error TS2503: Cannot find namespace 'Foo'. + } + + namespace Test3 { + export type Foo = { + bar: string; + } + + var x: Foo.bar = ""; + ~~~ +!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + } + + namespace Test4 { + export type Foo = { bar: number } + | { bar: string } + + var x: Foo.bar = ""; + ~~~ +!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + } + + namespace Test5 { + export type Foo = { bar: number } + | { wat: string } + + var x: Foo.bar = ""; + ~~~ +!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + } \ No newline at end of file diff --git a/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.js b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.js new file mode 100644 index 0000000000000..8a70396880bec --- /dev/null +++ b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.js @@ -0,0 +1,66 @@ +//// [errorForUsingPropertyOfTypeAsType01.ts] +namespace Test1 { + export interface Foo { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test2 { + export class Foo { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test3 { + export type Foo = { + bar: string; + } + + var x: Foo.bar = ""; +} + +namespace Test4 { + export type Foo = { bar: number } + | { bar: string } + + var x: Foo.bar = ""; +} + +namespace Test5 { + export type Foo = { bar: number } + | { wat: string } + + var x: Foo.bar = ""; +} + +//// [errorForUsingPropertyOfTypeAsType01.js] +var Test1; +(function (Test1) { + var x = ""; +})(Test1 || (Test1 = {})); +var Test2; +(function (Test2) { + var Foo = (function () { + function Foo() { + } + return Foo; + }()); + Test2.Foo = Foo; + var x = ""; +})(Test2 || (Test2 = {})); +var Test3; +(function (Test3) { + var x = ""; +})(Test3 || (Test3 = {})); +var Test4; +(function (Test4) { + var x = ""; +})(Test4 || (Test4 = {})); +var Test5; +(function (Test5) { + var x = ""; +})(Test5 || (Test5 = {})); From 497e3cfb68adfdf535a5c85791ec553a038101a6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 27 Jul 2017 11:44:26 -0700 Subject: [PATCH 3/5] Provide a more helpful error message when incorrectly using qualified names in the case of 'Type.propertyName'. --- src/compiler/checker.ts | 14 ++++++++++++++ src/compiler/diagnosticMessages.json | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fcfee1b468477..725a94e9d34ad 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1240,7 +1240,21 @@ namespace ts { function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { if (meaning === SymbolFlags.Namespace) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined)); + const parent = errorLocation.parent; if (symbol) { + if (isQualifiedName(parent)) { + const propName = parent.right.escapedText; + const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName); + if (propType) { + error( + parent, + 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, + unescapeLeadingUnderscores(name), + unescapeLeadingUnderscores(propName), + ); + return true; + } + } error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name)); return true; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7cd6108576cc2..0d9e7a0a6bf09 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2192,6 +2192,10 @@ "category": "Error", "code": 2712 }, + "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}\"]'?": { + "category": "Error", + "code": 2713 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", From e391439eaba8ac6db90b2676a167ef044dc1b366 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 27 Jul 2017 11:46:33 -0700 Subject: [PATCH 4/5] Accepted baselines. --- ...orForUsingPropertyOfTypeAsType01.errors.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt index 3285fe6a1d631..0dd9a597e9663 100644 --- a/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt +++ b/tests/baselines/reference/errorForUsingPropertyOfTypeAsType01.errors.txt @@ -1,7 +1,7 @@ -tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(6,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. +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"]'? tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(14,12): error TS2503: Cannot find namespace 'Foo'. -tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(22,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. -tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(29,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. +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"]'? +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"]'? tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. @@ -12,8 +12,8 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702 } var x: Foo.bar = ""; - ~~~ -!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + ~~~~~~~ +!!! 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"]'? } namespace Test2 { @@ -32,8 +32,8 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702 } var x: Foo.bar = ""; - ~~~ -!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + ~~~~~~~ +!!! 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"]'? } namespace Test4 { @@ -41,8 +41,8 @@ tests/cases/compiler/errorForUsingPropertyOfTypeAsType01.ts(36,12): error TS2702 | { bar: string } var x: Foo.bar = ""; - ~~~ -!!! error TS2702: 'Foo' only refers to a type, but is being used as a namespace here. + ~~~~~~~ +!!! 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"]'? } namespace Test5 { From 7c7f9adcc20c5143f68b228499a0b5268311616f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 27 Jul 2017 12:14:52 -0700 Subject: [PATCH 5/5] Added assertion. --- src/compiler/checker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 725a94e9d34ad..40d973ca9cef7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1243,6 +1243,7 @@ namespace ts { const parent = errorLocation.parent; if (symbol) { if (isQualifiedName(parent)) { + Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace"); const propName = parent.right.escapedText; const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName); if (propType) {