Skip to content

Commit e647933

Browse files
authored
Merge pull request #10333 from jwbay/better-type-as-value-error
Add clearer error message when types are used as values
2 parents 3d0547c + 0330877 commit e647933

30 files changed

+284
-69
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,8 @@ namespace ts {
877877
if (nameNotFoundMessage) {
878878
if (!errorLocation ||
879879
!checkAndReportErrorForMissingPrefix(errorLocation, name, nameArg) &&
880-
!checkAndReportErrorForExtendingInterface(errorLocation)) {
880+
!checkAndReportErrorForExtendingInterface(errorLocation) &&
881+
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning)) {
881882
error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
882883
}
883884
}
@@ -987,6 +988,16 @@ namespace ts {
987988
}
988989
}
989990

991+
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: string, meaning: SymbolFlags): boolean {
992+
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
993+
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined));
994+
if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) {
995+
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name);
996+
return true;
997+
}
998+
}
999+
return false;
1000+
}
9901001

9911002
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
9921003
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,10 @@
19471947
"category": "Error",
19481948
"code": 2692
19491949
},
1950+
"'{0}' only refers to a type, but is being used as a value here.": {
1951+
"category": "Error",
1952+
"code": 2693
1953+
},
19501954
"Import declaration '{0}' is using private name '{1}'.": {
19511955
"category": "Error",
19521956
"code": 4000

tests/baselines/reference/assignments.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(14,1): er
33
tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(17,1): error TS2364: Invalid left-hand side of assignment expression.
44
tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(18,1): error TS2450: Left-hand side of assignment expression cannot be a constant or a read-only property.
55
tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(21,1): error TS2364: Invalid left-hand side of assignment expression.
6-
tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(31,1): error TS2304: Cannot find name 'I'.
6+
tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(31,1): error TS2693: 'I' only refers to a type, but is being used as a value here.
77

88

99
==== tests/cases/conformance/expressions/valuesAndReferences/assignments.ts (6 errors) ====
@@ -49,4 +49,4 @@ tests/cases/conformance/expressions/valuesAndReferences/assignments.ts(31,1): er
4949
interface I { }
5050
I = null; // Error
5151
~
52-
!!! error TS2304: Cannot find name 'I'.
52+
!!! error TS2693: 'I' only refers to a type, but is being used as a value here.

tests/baselines/reference/classExtendsInterfaceInExpression.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/classExtendsInterfaceInExpression.ts(7,25): error TS2304: Cannot find name 'A'.
1+
tests/cases/compiler/classExtendsInterfaceInExpression.ts(7,25): error TS2693: 'A' only refers to a type, but is being used as a value here.
22

33

44
==== tests/cases/compiler/classExtendsInterfaceInExpression.ts (1 errors) ====
@@ -10,5 +10,5 @@ tests/cases/compiler/classExtendsInterfaceInExpression.ts(7,25): error TS2304: C
1010

1111
class C extends factory(A) {}
1212
~
13-
!!! error TS2304: Cannot find name 'A'.
13+
!!! error TS2693: 'A' only refers to a type, but is being used as a value here.
1414

tests/baselines/reference/errorsOnImportedSymbol.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
tests/cases/compiler/errorsOnImportedSymbol_1.ts(2,13): error TS2304: Cannot find name 'Sammy'.
2-
tests/cases/compiler/errorsOnImportedSymbol_1.ts(3,9): error TS2304: Cannot find name 'Sammy'.
1+
tests/cases/compiler/errorsOnImportedSymbol_1.ts(2,13): error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
2+
tests/cases/compiler/errorsOnImportedSymbol_1.ts(3,9): error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
33

44

55
==== tests/cases/compiler/errorsOnImportedSymbol_1.ts (2 errors) ====
66
import Sammy = require("./errorsOnImportedSymbol_0");
77
var x = new Sammy.Sammy();
88
~~~~~
9-
!!! error TS2304: Cannot find name 'Sammy'.
9+
!!! error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
1010
var y = Sammy.Sammy();
1111
~~~~~
12-
!!! error TS2304: Cannot find name 'Sammy'.
12+
!!! error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
1313

1414

1515
==== tests/cases/compiler/errorsOnImportedSymbol_0.ts (0 errors) ====

tests/baselines/reference/es6ExportEqualsInterop.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/main.ts(15,1): error TS2304: Cannot find name 'z1'.
1+
tests/cases/compiler/main.ts(15,1): error TS2693: 'z1' only refers to a type, but is being used as a value here.
22
tests/cases/compiler/main.ts(21,4): error TS2339: Property 'a' does not exist on type '() => any'.
33
tests/cases/compiler/main.ts(23,4): error TS2339: Property 'a' does not exist on type 'typeof Foo'.
44
tests/cases/compiler/main.ts(27,8): error TS1192: Module '"interface"' has no default export.
@@ -49,7 +49,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses
4949

5050
z1.a;
5151
~~
52-
!!! error TS2304: Cannot find name 'z1'.
52+
!!! error TS2693: 'z1' only refers to a type, but is being used as a value here.
5353
z2.a;
5454
z3.a;
5555
z4.a;

tests/baselines/reference/exportAssignmentOfDeclaredExternalModule.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
tests/cases/compiler/exportAssignmentOfDeclaredExternalModule_1.ts(3,13): error TS2304: Cannot find name 'Sammy'.
2-
tests/cases/compiler/exportAssignmentOfDeclaredExternalModule_1.ts(4,9): error TS2304: Cannot find name 'Sammy'.
1+
tests/cases/compiler/exportAssignmentOfDeclaredExternalModule_1.ts(3,13): error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
2+
tests/cases/compiler/exportAssignmentOfDeclaredExternalModule_1.ts(4,9): error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
33

44

55
==== tests/cases/compiler/exportAssignmentOfDeclaredExternalModule_1.ts (2 errors) ====
66
///<reference path='exportAssignmentOfDeclaredExternalModule_0.ts'/>
77
import Sammy = require('./exportAssignmentOfDeclaredExternalModule_0');
88
var x = new Sammy(); // error to use as constructor as there is not constructor symbol
99
~~~~~
10-
!!! error TS2304: Cannot find name 'Sammy'.
10+
!!! error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
1111
var y = Sammy(); // error to use interface name as call target
1212
~~~~~
13-
!!! error TS2304: Cannot find name 'Sammy'.
13+
!!! error TS2693: 'Sammy' only refers to a type, but is being used as a value here.
1414
var z: Sammy; // no error - z is of type interface Sammy from module 'M'
1515
var a = new z(); // constructor - no error
1616
var b = z(); // call signature - no error
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/genericConstructInvocationWithNoTypeArg.ts(4,27): error TS2304: Cannot find name 'Foo'.
1+
tests/cases/compiler/genericConstructInvocationWithNoTypeArg.ts(4,27): error TS2693: 'Foo' only refers to a type, but is being used as a value here.
22

33

44
==== tests/cases/compiler/genericConstructInvocationWithNoTypeArg.ts (1 errors) ====
@@ -7,5 +7,5 @@ tests/cases/compiler/genericConstructInvocationWithNoTypeArg.ts(4,27): error TS2
77
}
88
var f2: Foo<number> = new Foo(3);
99
~~~
10-
!!! error TS2304: Cannot find name 'Foo'.
10+
!!! error TS2693: 'Foo' only refers to a type, but is being used as a value here.
1111

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
tests/cases/compiler/inheritFromGenericTypeParameter.ts(1,20): error TS2304: Cannot find name 'T'.
1+
tests/cases/compiler/inheritFromGenericTypeParameter.ts(1,20): error TS2693: 'T' only refers to a type, but is being used as a value here.
22
tests/cases/compiler/inheritFromGenericTypeParameter.ts(2,24): error TS2312: An interface may only extend a class or another interface.
33

44

55
==== tests/cases/compiler/inheritFromGenericTypeParameter.ts (2 errors) ====
66
class C<T> extends T { }
77
~
8-
!!! error TS2304: Cannot find name 'T'.
8+
!!! error TS2693: 'T' only refers to a type, but is being used as a value here.
99
interface I<T> extends T { }
1010
~
1111
!!! error TS2312: An interface may only extend a class or another interface.

tests/baselines/reference/intTypeCheck.errors.txt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ tests/cases/compiler/intTypeCheck.ts(103,5): error TS2322: Type '() => void' is
1010
Property 'p' is missing in type '() => void'.
1111
tests/cases/compiler/intTypeCheck.ts(106,5): error TS2322: Type 'boolean' is not assignable to type 'i1'.
1212
tests/cases/compiler/intTypeCheck.ts(106,20): error TS1109: Expression expected.
13-
tests/cases/compiler/intTypeCheck.ts(106,21): error TS2304: Cannot find name 'i1'.
13+
tests/cases/compiler/intTypeCheck.ts(106,21): error TS2693: 'i1' only refers to a type, but is being used as a value here.
1414
tests/cases/compiler/intTypeCheck.ts(107,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
1515
tests/cases/compiler/intTypeCheck.ts(112,5): error TS2322: Type '{}' is not assignable to type 'i2'.
1616
Type '{}' provides no match for the signature '(): any'
@@ -21,7 +21,7 @@ tests/cases/compiler/intTypeCheck.ts(115,5): error TS2322: Type 'Base' is not as
2121
Type 'Base' provides no match for the signature '(): any'
2222
tests/cases/compiler/intTypeCheck.ts(120,5): error TS2322: Type 'boolean' is not assignable to type 'i2'.
2323
tests/cases/compiler/intTypeCheck.ts(120,21): error TS1109: Expression expected.
24-
tests/cases/compiler/intTypeCheck.ts(120,22): error TS2304: Cannot find name 'i2'.
24+
tests/cases/compiler/intTypeCheck.ts(120,22): error TS2693: 'i2' only refers to a type, but is being used as a value here.
2525
tests/cases/compiler/intTypeCheck.ts(121,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
2626
tests/cases/compiler/intTypeCheck.ts(126,5): error TS2322: Type '{}' is not assignable to type 'i3'.
2727
Type '{}' provides no match for the signature 'new (): any'
@@ -33,12 +33,12 @@ tests/cases/compiler/intTypeCheck.ts(131,5): error TS2322: Type '() => void' is
3333
Type '() => void' provides no match for the signature 'new (): any'
3434
tests/cases/compiler/intTypeCheck.ts(134,5): error TS2322: Type 'boolean' is not assignable to type 'i3'.
3535
tests/cases/compiler/intTypeCheck.ts(134,21): error TS1109: Expression expected.
36-
tests/cases/compiler/intTypeCheck.ts(134,22): error TS2304: Cannot find name 'i3'.
36+
tests/cases/compiler/intTypeCheck.ts(134,22): error TS2693: 'i3' only refers to a type, but is being used as a value here.
3737
tests/cases/compiler/intTypeCheck.ts(135,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
3838
tests/cases/compiler/intTypeCheck.ts(142,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
3939
tests/cases/compiler/intTypeCheck.ts(148,5): error TS2322: Type 'boolean' is not assignable to type 'i4'.
4040
tests/cases/compiler/intTypeCheck.ts(148,21): error TS1109: Expression expected.
41-
tests/cases/compiler/intTypeCheck.ts(148,22): error TS2304: Cannot find name 'i4'.
41+
tests/cases/compiler/intTypeCheck.ts(148,22): error TS2693: 'i4' only refers to a type, but is being used as a value here.
4242
tests/cases/compiler/intTypeCheck.ts(149,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
4343
tests/cases/compiler/intTypeCheck.ts(154,5): error TS2322: Type '{}' is not assignable to type 'i5'.
4444
Property 'p' is missing in type '{}'.
@@ -51,7 +51,7 @@ tests/cases/compiler/intTypeCheck.ts(159,5): error TS2322: Type '() => void' is
5151
Property 'p' is missing in type '() => void'.
5252
tests/cases/compiler/intTypeCheck.ts(162,5): error TS2322: Type 'boolean' is not assignable to type 'i5'.
5353
tests/cases/compiler/intTypeCheck.ts(162,21): error TS1109: Expression expected.
54-
tests/cases/compiler/intTypeCheck.ts(162,22): error TS2304: Cannot find name 'i5'.
54+
tests/cases/compiler/intTypeCheck.ts(162,22): error TS2693: 'i5' only refers to a type, but is being used as a value here.
5555
tests/cases/compiler/intTypeCheck.ts(163,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
5656
tests/cases/compiler/intTypeCheck.ts(168,5): error TS2322: Type '{}' is not assignable to type 'i6'.
5757
Type '{}' provides no match for the signature '(): any'
@@ -64,7 +64,7 @@ tests/cases/compiler/intTypeCheck.ts(173,5): error TS2322: Type '() => void' is
6464
Type 'void' is not assignable to type 'number'.
6565
tests/cases/compiler/intTypeCheck.ts(176,5): error TS2322: Type 'boolean' is not assignable to type 'i6'.
6666
tests/cases/compiler/intTypeCheck.ts(176,21): error TS1109: Expression expected.
67-
tests/cases/compiler/intTypeCheck.ts(176,22): error TS2304: Cannot find name 'i6'.
67+
tests/cases/compiler/intTypeCheck.ts(176,22): error TS2693: 'i6' only refers to a type, but is being used as a value here.
6868
tests/cases/compiler/intTypeCheck.ts(177,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
6969
tests/cases/compiler/intTypeCheck.ts(182,5): error TS2322: Type '{}' is not assignable to type 'i7'.
7070
Type '{}' provides no match for the signature 'new (): any'
@@ -76,12 +76,12 @@ tests/cases/compiler/intTypeCheck.ts(187,5): error TS2322: Type '() => void' is
7676
Type '() => void' provides no match for the signature 'new (): any'
7777
tests/cases/compiler/intTypeCheck.ts(190,5): error TS2322: Type 'boolean' is not assignable to type 'i7'.
7878
tests/cases/compiler/intTypeCheck.ts(190,21): error TS1109: Expression expected.
79-
tests/cases/compiler/intTypeCheck.ts(190,22): error TS2304: Cannot find name 'i7'.
79+
tests/cases/compiler/intTypeCheck.ts(190,22): error TS2693: 'i7' only refers to a type, but is being used as a value here.
8080
tests/cases/compiler/intTypeCheck.ts(191,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
8181
tests/cases/compiler/intTypeCheck.ts(198,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
8282
tests/cases/compiler/intTypeCheck.ts(204,5): error TS2322: Type 'boolean' is not assignable to type 'i8'.
8383
tests/cases/compiler/intTypeCheck.ts(204,21): error TS1109: Expression expected.
84-
tests/cases/compiler/intTypeCheck.ts(204,22): error TS2304: Cannot find name 'i8'.
84+
tests/cases/compiler/intTypeCheck.ts(204,22): error TS2693: 'i8' only refers to a type, but is being used as a value here.
8585
tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
8686

8787

@@ -214,7 +214,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
214214
~
215215
!!! error TS1109: Expression expected.
216216
~~
217-
!!! error TS2304: Cannot find name 'i1'.
217+
!!! error TS2693: 'i1' only refers to a type, but is being used as a value here.
218218
var obj10: i1 = new {};
219219
~~~~~~
220220
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -247,7 +247,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
247247
~
248248
!!! error TS1109: Expression expected.
249249
~~
250-
!!! error TS2304: Cannot find name 'i2'.
250+
!!! error TS2693: 'i2' only refers to a type, but is being used as a value here.
251251
var obj21: i2 = new {};
252252
~~~~~~
253253
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -281,7 +281,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
281281
~
282282
!!! error TS1109: Expression expected.
283283
~~
284-
!!! error TS2304: Cannot find name 'i3'.
284+
!!! error TS2693: 'i3' only refers to a type, but is being used as a value here.
285285
var obj32: i3 = new {};
286286
~~~~~~
287287
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -305,7 +305,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
305305
~
306306
!!! error TS1109: Expression expected.
307307
~~
308-
!!! error TS2304: Cannot find name 'i4'.
308+
!!! error TS2693: 'i4' only refers to a type, but is being used as a value here.
309309
var obj43: i4 = new {};
310310
~~~~~~
311311
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -341,7 +341,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
341341
~
342342
!!! error TS1109: Expression expected.
343343
~~
344-
!!! error TS2304: Cannot find name 'i5'.
344+
!!! error TS2693: 'i5' only refers to a type, but is being used as a value here.
345345
var obj54: i5 = new {};
346346
~~~~~~
347347
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -377,7 +377,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
377377
~
378378
!!! error TS1109: Expression expected.
379379
~~
380-
!!! error TS2304: Cannot find name 'i6'.
380+
!!! error TS2693: 'i6' only refers to a type, but is being used as a value here.
381381
var obj65: i6 = new {};
382382
~~~~~~
383383
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -411,7 +411,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
411411
~
412412
!!! error TS1109: Expression expected.
413413
~~
414-
!!! error TS2304: Cannot find name 'i7'.
414+
!!! error TS2693: 'i7' only refers to a type, but is being used as a value here.
415415
var obj76: i7 = new {};
416416
~~~~~~
417417
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
@@ -435,7 +435,7 @@ tests/cases/compiler/intTypeCheck.ts(205,17): error TS2351: Cannot use 'new' wit
435435
~
436436
!!! error TS1109: Expression expected.
437437
~~
438-
!!! error TS2304: Cannot find name 'i8'.
438+
!!! error TS2693: 'i8' only refers to a type, but is being used as a value here.
439439
var obj87: i8 = new {};
440440
~~~~~~
441441
!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

0 commit comments

Comments
 (0)