Skip to content

Fix46246 #46357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 31, 2022
Merged

Fix46246 #46357

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
18 changes: 17 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2478,7 +2478,12 @@ namespace ts {
function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean {
if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) {
if (isPrimitiveTypeName(name)) {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
if (isExtendedByInterface(errorLocation)) {
error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name));
}
else {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name));
}
return true;
}
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
Expand All @@ -2499,6 +2504,17 @@ namespace ts {
return false;
}

function isExtendedByInterface(node: Node): boolean {
const grandparent = node.parent.parent;
const parentOfGrandparent = grandparent.parent;
if(grandparent && parentOfGrandparent){
const isExtending = isHeritageClause(grandparent) && grandparent.token === SyntaxKind.ExtendsKeyword;
const isInterface = isInterfaceDeclaration(parentOfGrandparent);
return isExtending && isInterface;
}
return false;
}

function maybeMappedType(node: Node, symbol: Symbol) {
const container = findAncestor(node.parent, n =>
isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | 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 @@ -3475,6 +3475,10 @@
"category": "Error",
"code": 2839
},
"An interface cannot extend a primitive type like '{0}'; an interface can only extend named types and classes": {
"category": "Error",
"code": 2840
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
tests/cases/compiler/errorLocationForInterfaceExtension.ts(3,21): error TS2693: 'string' only refers to a type, but is being used as a value here.
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


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

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

Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(14,5): error TS2411: Prop
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(15,5): error TS2411: Property 'p5' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(19,5): error TS2411: Property 'f3' of type '(a: string) => number' is not assignable to 'string' index type '() => string'.
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Property 'f4' of type '(s: number) => string' is not assignable to 'string' index type '() => string'.
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
tests/cases/compiler/interfacedeclWithIndexerErrors.ts(48,18): error TS2693: 'string' only refers to a type, but is being used as a value here.


==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (5 errors) ====
==== tests/cases/compiler/interfacedeclWithIndexerErrors.ts (7 errors) ====
interface a0 {
(): string;
(a, b, c?: string): number;
Expand Down Expand Up @@ -59,6 +61,17 @@ tests/cases/compiler/interfacedeclWithIndexerErrors.ts(20,5): error TS2411: Prop
interface d extends a {
}

interface e extends number {
~~~~~~
!!! error TS2840: An interface cannot extend a primitive type like 'number'; an interface can only extend named types and classes
}

interface f {
prop: typeof string;
~~~~~~
!!! error TS2693: 'string' only refers to a type, but is being used as a value here.
}

class c1 implements a {
}
var instance2 = new c1();
7 changes: 7 additions & 0 deletions tests/baselines/reference/interfacedeclWithIndexerErrors.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ interface c extends a, b {
interface d extends a {
}

interface e extends number {
}

interface f {
prop: typeof string;
}

class c1 implements a {
}
var instance2 = new c1();
Expand Down
17 changes: 14 additions & 3 deletions tests/baselines/reference/interfacedeclWithIndexerErrors.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,22 @@ interface d extends a {
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
}

interface e extends number {
>e : Symbol(e, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
}

interface f {
>f : Symbol(f, Decl(interfacedeclWithIndexerErrors.ts, 44, 1))

prop: typeof string;
>prop : Symbol(f.prop, Decl(interfacedeclWithIndexerErrors.ts, 46, 13))
}

class c1 implements a {
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))
>a : Symbol(a, Decl(interfacedeclWithIndexerErrors.ts, 29, 1))
}
var instance2 = new c1();
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 45, 3))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 41, 1))
>instance2 : Symbol(instance2, Decl(interfacedeclWithIndexerErrors.ts, 52, 3))
>c1 : Symbol(c1, Decl(interfacedeclWithIndexerErrors.ts, 48, 1))

Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ interface c extends a, b {
interface d extends a {
}

interface e extends number {
}

interface f {
prop: typeof string;
>prop : any
>string : any
}

class c1 implements a {
>c1 : c1
}
Expand Down
7 changes: 7 additions & 0 deletions tests/cases/compiler/interfacedeclWithIndexerErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ interface c extends a, b {
interface d extends a {
}

interface e extends number {
}

interface f {
prop: typeof string;
}

class c1 implements a {
}
var instance2 = new c1();