Skip to content

Commit 75f4e95

Browse files
HarsheetKakarharsheetkakarsandersn
authored
Fix46246 (#46357)
* changed error message for interface extending primitive type * moved interface check to different function * changed part of interface declaration to is extended by interface Co-authored-by: harsheetkakar <[email protected]> Co-authored-by: Nathan Shively-Sanders <[email protected]>
1 parent 44b9745 commit 75f4e95

8 files changed

+74
-7
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2478,7 +2478,12 @@ namespace ts {
24782478
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
24792479
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
24802480
if (isPrimitiveTypeName(name)) {
2481-
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
2481+
if (isExtendedByInterface(errorLocation)) {
2482+
error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name));
2483+
}
2484+
else {
2485+
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
2486+
}
24822487
return true;
24832488
}
24842489
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
@@ -2499,6 +2504,17 @@ namespace ts {
24992504
return false;
25002505
}
25012506

2507+
function isExtendedByInterface(node: Node): boolean {
2508+
const grandparent = node.parent.parent;
2509+
const parentOfGrandparent = grandparent.parent;
2510+
if(grandparent && parentOfGrandparent){
2511+
const isExtending = isHeritageClause(grandparent) && grandparent.token === SyntaxKind.ExtendsKeyword;
2512+
const isInterface = isInterfaceDeclaration(parentOfGrandparent);
2513+
return isExtending && isInterface;
2514+
}
2515+
return false;
2516+
}
2517+
25022518
function maybeMappedType(node: Node, symbol: Symbol) {
25032519
const container = findAncestor(node.parent, n =>
25042520
isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined;

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3475,6 +3475,10 @@
34753475
"category": "Error",
34763476
"code": 2839
34773477
},
3478+
"An interface cannot extend a primitive type like '{0}'; an interface can only extend named types and classes": {
3479+
"category": "Error",
3480+
"code": 2840
3481+
},
34783482

34793483
"Import declaration '{0}' is using private name '{1}'.": {
34803484
"category": "Error",
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2693: 'string' only refers to a type, but is being used as a value here.
1+
tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2840: An interface cannot extend a primitive type like 'string'; an interface can only extend named types and classes
22

33

44
==== tests/cases/compiler/errorLocationForInterfaceExtension.ts (1 errors) ====
55
var n = '';
66

77
interface x extends string { }
88
~~~~~~
9-
!!! error TS2693: 'string' only refers to a type, but is being used as a value here.
9+
!!! error TS2840: An interface cannot extend a primitive type like 'string'; an interface can only extend named types and classes
1010

tests/baselines/reference/interfacedeclWithIndexerErrors.errors.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(14,5): error TS2411: Prop
33
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(15,5): error TS2411: Property 'p5' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
44
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(19,5): error TS2411: Property 'f3' of type '(a: string) => number' is not assignable to 'string' index type '() => string'.
55
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Property 'f4' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
6+
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(44,21): error TS2840: An interface cannot extend a primitive type like 'number'; an interface can only extend named types and classes
7+
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(48,18): error TS2693: 'string' only refers to a type, but is being used as a value here.
68

79

8-
==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (5 errors) ====
10+
==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (7 errors) ====
911
interface a0 {
1012
(): string;
1113
(a, b, c?: string): number;
@@ -59,6 +61,17 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Prop
5961
interface d extends a {
6062
}
6163

64+
interface e extends number {
65+
~~~~~~
66+
!!! error TS2840: An interface cannot extend a primitive type like 'number'; an interface can only extend named types and classes
67+
}
68+
69+
interface f {
70+
prop: typeof string;
71+
~~~~~~
72+
!!! error TS2693: 'string' only refers to a type, but is being used as a value here.
73+
}
74+
6275
class c1 implements a {
6376
}
6477
var instance2 = new c1();

tests/baselines/reference/interfacedeclWithIndexerErrors.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ interface c extends a, b {
4242
interface d extends a {
4343
}
4444

45+
interface e extends number {
46+
}
47+
48+
interface f {
49+
prop: typeof string;
50+
}
51+
4552
class c1 implements a {
4653
}
4754
var instance2 = new c1();

tests/baselines/reference/interfacedeclWithIndexerErrors.symbols

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,22 @@ interface d extends a {
8484
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
8585
}
8686

87+
interface e extends number {
88+
>e : Symbol(e, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
89+
}
90+
91+
interface f {
92+
>f : Symbol(f, Decl(interfacedeclWithIndexerErrors.ts, 44, 1))
93+
94+
prop: typeof string;
95+
>prop : Symbol(f.prop, Decl(interfacedeclWithIndexerErrors.ts, 46, 13))
96+
}
97+
8798
class c1 implements a {
88-
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
99+
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))
89100
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
90101
}
91102
var instance2 = new c1();
92-
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 45, 3))
93-
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
103+
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 52, 3))
104+
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))
94105

tests/baselines/reference/interfacedeclWithIndexerErrors.types

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ interface c extends a, b {
7070
interface d extends a {
7171
}
7272

73+
interface e extends number {
74+
}
75+
76+
interface f {
77+
prop: typeof string;
78+
>prop : any
79+
>string : any
80+
}
81+
7382
class c1 implements a {
7483
>c1 : c1
7584
}

tests/cases/compiler/interfacedeclWithIndexerErrors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ interface c extends a, b {
4141
interface d extends a {
4242
}
4343

44+
interface e extends number {
45+
}
46+
47+
interface f {
48+
prop: typeof string;
49+
}
50+
4451
class c1 implements a {
4552
}
4653
var instance2 = new c1();

0 commit comments

Comments
 (0)