Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@ namespace ts {
if (!errorLocation ||
!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) &&
!checkAndReportErrorForExtendingInterface(errorLocation) &&
!checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) {
error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
}
Expand Down Expand Up @@ -1032,6 +1033,18 @@ 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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SymbolFlags.Type & ~SymbolFlags.Value excludes classes and enums. Was that intentional? cc @DanielRosenwasser

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it should have been & ~SymbolFlags.Namespace instead

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be missing something, but I don't think SymbolFlags.Type includes SymbolFlags.Namespace.

if (symbol) {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name);
return true;
}
}

return false;
}

function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean {
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined));
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,10 @@
"category": "Error",
"code": 2701
},
"'{0}' only refers to a type, but is being used as a namespace here.": {
"category": "Error",
"code": 2702
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts(5,12): error TS2503: Cannot find namespace 'V'.
tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts(11,12): error TS2503: Cannot find namespace 'C'.
tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts(23,12): error TS2693: 'I' only refers to a type, but is being used as a value here.
tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts(23,12): error TS2702: 'I' only refers to a type, but is being used as a namespace here.


==== tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIdentifiers.ts (3 errors) ====
Expand Down Expand Up @@ -32,5 +32,5 @@ tests/cases/conformance/internalModules/importDeclarations/invalidImportAliasIde

import i = I;
~
!!! error TS2693: 'I' only refers to a type, but is being used as a value here.
!!! error TS2702: 'I' only refers to a type, but is being used as a namespace here.

11 changes: 11 additions & 0 deletions tests/baselines/reference/invalidUseOfTypeAsNamespace.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
tests/cases/compiler/invalidUseOfTypeAsNamespace.ts(4,16): error TS2702: 'OhNo' only refers to a type, but is being used as a namespace here.


==== tests/cases/compiler/invalidUseOfTypeAsNamespace.ts (1 errors) ====
interface OhNo {
}

declare let y: OhNo.hello;
~~~~
!!! error TS2702: 'OhNo' only refers to a type, but is being used as a namespace here.

8 changes: 8 additions & 0 deletions tests/baselines/reference/invalidUseOfTypeAsNamespace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//// [invalidUseOfTypeAsNamespace.ts]
interface OhNo {
}

declare let y: OhNo.hello;


//// [invalidUseOfTypeAsNamespace.js]
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(21,9): error TS
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(21,17): error TS1213: Identifier expected. 'private' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(23,20): error TS1213: Identifier expected. 'public' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(25,20): error TS1213: Identifier expected. 'public' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(25,20): error TS2693: 'public' only refers to a type, but is being used as a value here.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(25,20): error TS2702: 'public' only refers to a type, but is being used as a namespace here.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(26,21): error TS1213: Identifier expected. 'public' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(26,21): error TS2693: 'public' only refers to a type, but is being used as a value here.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(26,21): error TS2702: 'public' only refers to a type, but is being used as a namespace here.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(27,17): error TS1213: Identifier expected. 'package' is a reserved word in strict mode. Class definitions are automatically in strict mode.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(27,17): error TS2304: Cannot find name 'package'.
tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(28,17): error TS1213: Identifier expected. 'package' is a reserved word in strict mode. Class definitions are automatically in strict mode.
Expand Down Expand Up @@ -88,12 +88,12 @@ tests/cases/compiler/strictModeReservedWordInClassDeclaration.ts(28,17): error T
~~~~~~
!!! error TS1213: Identifier expected. 'public' is a reserved word in strict mode. Class definitions are automatically in strict mode.
~~~~~~
!!! error TS2693: 'public' only refers to a type, but is being used as a value here.
!!! error TS2702: 'public' only refers to a type, but is being used as a namespace here.
class F1 implements public.private.implements { }
~~~~~~
!!! error TS1213: Identifier expected. 'public' is a reserved word in strict mode. Class definitions are automatically in strict mode.
~~~~~~
!!! error TS2693: 'public' only refers to a type, but is being used as a value here.
!!! error TS2702: 'public' only refers to a type, but is being used as a namespace here.
class G extends package { }
~~~~~~~
!!! error TS1213: Identifier expected. 'package' is a reserved word in strict mode. Class definitions are automatically in strict mode.
Expand Down
4 changes: 4 additions & 0 deletions tests/cases/compiler/invalidUseOfTypeAsNamespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface OhNo {
}

declare let y: OhNo.hello;