diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cc8a7f7428fcf..3d044fa5bf0f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3458,10 +3458,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (containerKind === SyntaxKind.InterfaceDeclaration && heritageKind === SyntaxKind.ExtendsKeyword) { error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_It_can_only_extend_other_named_object_types, unescapeLeadingUnderscores(name)); } - else if (containerKind === SyntaxKind.ClassDeclaration && heritageKind === SyntaxKind.ExtendsKeyword) { + else if (isClassLike(grandparent.parent) && heritageKind === SyntaxKind.ExtendsKeyword) { error(errorLocation, Diagnostics.A_class_cannot_extend_a_primitive_type_like_0_Classes_can_only_extend_constructable_values, unescapeLeadingUnderscores(name)); } - else if (containerKind === SyntaxKind.ClassDeclaration && heritageKind === SyntaxKind.ImplementsKeyword) { + else if (isClassLike(grandparent.parent) && heritageKind === SyntaxKind.ImplementsKeyword) { error(errorLocation, Diagnostics.A_class_cannot_implement_a_primitive_type_like_0_It_can_only_implement_other_named_object_types, unescapeLeadingUnderscores(name)); } } diff --git a/tests/baselines/reference/classExtendingPrimitive.errors.txt b/tests/baselines/reference/classExtendingPrimitive.errors.txt index 1dceab8bcd6a6..be4615ff35a26 100644 --- a/tests/baselines/reference/classExtendingPrimitive.errors.txt +++ b/tests/baselines/reference/classExtendingPrimitive.errors.txt @@ -7,9 +7,15 @@ classExtendingPrimitive.ts(8,18): error TS2304: Cannot find name 'Null'. classExtendingPrimitive.ts(10,18): error TS2507: Type 'undefined' is not a constructor function type. classExtendingPrimitive.ts(11,18): error TS2552: Cannot find name 'Undefined'. Did you mean 'undefined'? classExtendingPrimitive.ts(14,18): error TS2507: Type 'typeof E' is not a constructor function type. +classExtendingPrimitive.ts(16,26): error TS2863: A class cannot extend a primitive type like 'number'. Classes can only extend constructable values. +classExtendingPrimitive.ts(17,27): error TS2863: A class cannot extend a primitive type like 'string'. Classes can only extend constructable values. +classExtendingPrimitive.ts(18,27): error TS2863: A class cannot extend a primitive type like 'boolean'. Classes can only extend constructable values. +classExtendingPrimitive.ts(20,29): error TS2863: A class cannot extend a primitive type like 'number'. Classes can only extend constructable values. +classExtendingPrimitive.ts(21,29): error TS2863: A class cannot extend a primitive type like 'string'. Classes can only extend constructable values. +classExtendingPrimitive.ts(22,29): error TS2863: A class cannot extend a primitive type like 'boolean'. Classes can only extend constructable values. -==== classExtendingPrimitive.ts (9 errors) ==== +==== classExtendingPrimitive.ts (15 errors) ==== // classes cannot extend primitives class C extends number { } @@ -41,4 +47,25 @@ classExtendingPrimitive.ts(14,18): error TS2507: Type 'typeof E' is not a constr enum E { A } class C8 extends E { } ~ -!!! error TS2507: Type 'typeof E' is not a constructor function type. \ No newline at end of file +!!! error TS2507: Type 'typeof E' is not a constructor function type. + + const C9 = class extends number { } + ~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'number'. Classes can only extend constructable values. + const C10 = class extends string { } + ~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'string'. Classes can only extend constructable values. + const C11 = class extends boolean { } + ~~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'boolean'. Classes can only extend constructable values. + + const C12 = class A extends number { } + ~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'number'. Classes can only extend constructable values. + const C13 = class B extends string { } + ~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'string'. Classes can only extend constructable values. + const C14 = class C extends boolean { } + ~~~~~~~ +!!! error TS2863: A class cannot extend a primitive type like 'boolean'. Classes can only extend constructable values. + \ No newline at end of file diff --git a/tests/baselines/reference/classExtendingPrimitive.js b/tests/baselines/reference/classExtendingPrimitive.js index 86ff82bc42e23..5afe16d1bd274 100644 --- a/tests/baselines/reference/classExtendingPrimitive.js +++ b/tests/baselines/reference/classExtendingPrimitive.js @@ -14,7 +14,16 @@ class C6 extends undefined { } class C7 extends Undefined { } enum E { A } -class C8 extends E { } +class C8 extends E { } + +const C9 = class extends number { } +const C10 = class extends string { } +const C11 = class extends boolean { } + +const C12 = class A extends number { } +const C13 = class B extends string { } +const C14 = class C extends boolean { } + //// [classExtendingPrimitive.js] // classes cannot extend primitives @@ -105,3 +114,45 @@ var C8 = /** @class */ (function (_super) { } return C8; }(E)); +var C9 = /** @class */ (function (_super) { + __extends(C9, _super); + function C9() { + return _super !== null && _super.apply(this, arguments) || this; + } + return C9; +}(number)); +var C10 = /** @class */ (function (_super) { + __extends(C10, _super); + function C10() { + return _super !== null && _super.apply(this, arguments) || this; + } + return C10; +}(string)); +var C11 = /** @class */ (function (_super) { + __extends(C11, _super); + function C11() { + return _super !== null && _super.apply(this, arguments) || this; + } + return C11; +}(boolean)); +var C12 = /** @class */ (function (_super) { + __extends(A, _super); + function A() { + return _super !== null && _super.apply(this, arguments) || this; + } + return A; +}(number)); +var C13 = /** @class */ (function (_super) { + __extends(B, _super); + function B() { + return _super !== null && _super.apply(this, arguments) || this; + } + return B; +}(string)); +var C14 = /** @class */ (function (_super) { + __extends(C, _super); + function C() { + return _super !== null && _super.apply(this, arguments) || this; + } + return C; +}(boolean)); diff --git a/tests/baselines/reference/classExtendingPrimitive.symbols b/tests/baselines/reference/classExtendingPrimitive.symbols index c9bcfad9c7b9c..0b6ccd61faea1 100644 --- a/tests/baselines/reference/classExtendingPrimitive.symbols +++ b/tests/baselines/reference/classExtendingPrimitive.symbols @@ -39,3 +39,24 @@ class C8 extends E { } >C8 : Symbol(C8, Decl(classExtendingPrimitive.ts, 12, 12)) >E : Symbol(E, Decl(classExtendingPrimitive.ts, 10, 30)) +const C9 = class extends number { } +>C9 : Symbol(C9, Decl(classExtendingPrimitive.ts, 15, 5)) + +const C10 = class extends string { } +>C10 : Symbol(C10, Decl(classExtendingPrimitive.ts, 16, 5)) + +const C11 = class extends boolean { } +>C11 : Symbol(C11, Decl(classExtendingPrimitive.ts, 17, 5)) + +const C12 = class A extends number { } +>C12 : Symbol(C12, Decl(classExtendingPrimitive.ts, 19, 5)) +>A : Symbol(A, Decl(classExtendingPrimitive.ts, 19, 11)) + +const C13 = class B extends string { } +>C13 : Symbol(C13, Decl(classExtendingPrimitive.ts, 20, 5)) +>B : Symbol(B, Decl(classExtendingPrimitive.ts, 20, 11)) + +const C14 = class C extends boolean { } +>C14 : Symbol(C14, Decl(classExtendingPrimitive.ts, 21, 5)) +>C : Symbol(C, Decl(classExtendingPrimitive.ts, 21, 11)) + diff --git a/tests/baselines/reference/classExtendingPrimitive.types b/tests/baselines/reference/classExtendingPrimitive.types index d3378fb79b2f0..e7d020fa99e88 100644 --- a/tests/baselines/reference/classExtendingPrimitive.types +++ b/tests/baselines/reference/classExtendingPrimitive.types @@ -69,3 +69,57 @@ class C8 extends E { } >E : typeof E > : ^^^^^^^^ +const C9 = class extends number { } +>C9 : typeof C9 +> : ^^^^^^^^^ +>class extends number { } : typeof C9 +> : ^^^^^^^^^ +>number : any +> : ^^^ + +const C10 = class extends string { } +>C10 : typeof C10 +> : ^^^^^^^^^^ +>class extends string { } : typeof C10 +> : ^^^^^^^^^^ +>string : any +> : ^^^ + +const C11 = class extends boolean { } +>C11 : typeof C11 +> : ^^^^^^^^^^ +>class extends boolean { } : typeof C11 +> : ^^^^^^^^^^ +>boolean : any +> : ^^^ + +const C12 = class A extends number { } +>C12 : typeof A +> : ^^^^^^^^ +>class A extends number { } : typeof A +> : ^^^^^^^^ +>A : typeof A +> : ^^^^^^^^ +>number : any +> : ^^^ + +const C13 = class B extends string { } +>C13 : typeof B +> : ^^^^^^^^ +>class B extends string { } : typeof B +> : ^^^^^^^^ +>B : typeof B +> : ^^^^^^^^ +>string : any +> : ^^^ + +const C14 = class C extends boolean { } +>C14 : typeof C +> : ^^^^^^^^ +>class C extends boolean { } : typeof C +> : ^^^^^^^^ +>C : typeof C +> : ^^^^^^^^ +>boolean : any +> : ^^^ + diff --git a/tests/baselines/reference/classImplementsPrimitive.errors.txt b/tests/baselines/reference/classImplementsPrimitive.errors.txt index 1ad273ca481a2..166053a24a367 100644 --- a/tests/baselines/reference/classImplementsPrimitive.errors.txt +++ b/tests/baselines/reference/classImplementsPrimitive.errors.txt @@ -1,9 +1,15 @@ classImplementsPrimitive.ts(3,20): error TS2864: A class cannot implement a primitive type like 'number'. It can only implement other named object types. classImplementsPrimitive.ts(4,21): error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. classImplementsPrimitive.ts(5,21): error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. +classImplementsPrimitive.ts(7,29): error TS2864: A class cannot implement a primitive type like 'number'. It can only implement other named object types. +classImplementsPrimitive.ts(8,29): error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. +classImplementsPrimitive.ts(9,29): error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. +classImplementsPrimitive.ts(11,31): error TS2864: A class cannot implement a primitive type like 'number'. It can only implement other named object types. +classImplementsPrimitive.ts(12,31): error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. +classImplementsPrimitive.ts(13,31): error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. -==== classImplementsPrimitive.ts (3 errors) ==== +==== classImplementsPrimitive.ts (9 errors) ==== // classes cannot implement primitives class C implements number { } @@ -14,4 +20,25 @@ classImplementsPrimitive.ts(5,21): error TS2864: A class cannot implement a prim !!! error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. class C3 implements boolean { } ~~~~~~~ -!!! error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. \ No newline at end of file +!!! error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. + + const C4 = class implements number {} + ~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'number'. It can only implement other named object types. + const C5 = class implements string {} + ~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. + const C6 = class implements boolean {} + ~~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. + + const C7 = class A implements number { } + ~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'number'. It can only implement other named object types. + const C8 = class B implements string { } + ~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'string'. It can only implement other named object types. + const C9 = class C implements boolean { } + ~~~~~~~ +!!! error TS2864: A class cannot implement a primitive type like 'boolean'. It can only implement other named object types. + \ No newline at end of file diff --git a/tests/baselines/reference/classImplementsPrimitive.js b/tests/baselines/reference/classImplementsPrimitive.js index c8daf7b6d17eb..e99e0061bcdef 100644 --- a/tests/baselines/reference/classImplementsPrimitive.js +++ b/tests/baselines/reference/classImplementsPrimitive.js @@ -5,7 +5,16 @@ class C implements number { } class C2 implements string { } -class C3 implements boolean { } +class C3 implements boolean { } + +const C4 = class implements number {} +const C5 = class implements string {} +const C6 = class implements boolean {} + +const C7 = class A implements number { } +const C8 = class B implements string { } +const C9 = class C implements boolean { } + //// [classImplementsPrimitive.js] // classes cannot implement primitives @@ -24,3 +33,33 @@ var C3 = /** @class */ (function () { } return C3; }()); +var C4 = /** @class */ (function () { + function class_1() { + } + return class_1; +}()); +var C5 = /** @class */ (function () { + function class_2() { + } + return class_2; +}()); +var C6 = /** @class */ (function () { + function class_3() { + } + return class_3; +}()); +var C7 = /** @class */ (function () { + function A() { + } + return A; +}()); +var C8 = /** @class */ (function () { + function B() { + } + return B; +}()); +var C9 = /** @class */ (function () { + function C() { + } + return C; +}()); diff --git a/tests/baselines/reference/classImplementsPrimitive.symbols b/tests/baselines/reference/classImplementsPrimitive.symbols index b749f8423a134..b979d2b6eeb9d 100644 --- a/tests/baselines/reference/classImplementsPrimitive.symbols +++ b/tests/baselines/reference/classImplementsPrimitive.symbols @@ -12,3 +12,24 @@ class C2 implements string { } class C3 implements boolean { } >C3 : Symbol(C3, Decl(classImplementsPrimitive.ts, 3, 30)) +const C4 = class implements number {} +>C4 : Symbol(C4, Decl(classImplementsPrimitive.ts, 6, 5)) + +const C5 = class implements string {} +>C5 : Symbol(C5, Decl(classImplementsPrimitive.ts, 7, 5)) + +const C6 = class implements boolean {} +>C6 : Symbol(C6, Decl(classImplementsPrimitive.ts, 8, 5)) + +const C7 = class A implements number { } +>C7 : Symbol(C7, Decl(classImplementsPrimitive.ts, 10, 5)) +>A : Symbol(A, Decl(classImplementsPrimitive.ts, 10, 10)) + +const C8 = class B implements string { } +>C8 : Symbol(C8, Decl(classImplementsPrimitive.ts, 11, 5)) +>B : Symbol(B, Decl(classImplementsPrimitive.ts, 11, 10)) + +const C9 = class C implements boolean { } +>C9 : Symbol(C9, Decl(classImplementsPrimitive.ts, 12, 5)) +>C : Symbol(C, Decl(classImplementsPrimitive.ts, 12, 10)) + diff --git a/tests/baselines/reference/classImplementsPrimitive.types b/tests/baselines/reference/classImplementsPrimitive.types index 7847e207a4cf2..f7bcaada228a5 100644 --- a/tests/baselines/reference/classImplementsPrimitive.types +++ b/tests/baselines/reference/classImplementsPrimitive.types @@ -15,3 +15,45 @@ class C3 implements boolean { } >C3 : C3 > : ^^ +const C4 = class implements number {} +>C4 : typeof C4 +> : ^^^^^^^^^ +>class implements number {} : typeof C4 +> : ^^^^^^^^^ + +const C5 = class implements string {} +>C5 : typeof C5 +> : ^^^^^^^^^ +>class implements string {} : typeof C5 +> : ^^^^^^^^^ + +const C6 = class implements boolean {} +>C6 : typeof C6 +> : ^^^^^^^^^ +>class implements boolean {} : typeof C6 +> : ^^^^^^^^^ + +const C7 = class A implements number { } +>C7 : typeof A +> : ^^^^^^^^ +>class A implements number { } : typeof A +> : ^^^^^^^^ +>A : typeof A +> : ^^^^^^^^ + +const C8 = class B implements string { } +>C8 : typeof B +> : ^^^^^^^^ +>class B implements string { } : typeof B +> : ^^^^^^^^ +>B : typeof B +> : ^^^^^^^^ + +const C9 = class C implements boolean { } +>C9 : typeof C +> : ^^^^^^^^ +>class C implements boolean { } : typeof C +> : ^^^^^^^^ +>C : typeof C +> : ^^^^^^^^ + diff --git a/tests/cases/compiler/classImplementsPrimitive.ts b/tests/cases/compiler/classImplementsPrimitive.ts index 0da45d562e007..447f9f7a59a9b 100644 --- a/tests/cases/compiler/classImplementsPrimitive.ts +++ b/tests/cases/compiler/classImplementsPrimitive.ts @@ -2,4 +2,12 @@ class C implements number { } class C2 implements string { } -class C3 implements boolean { } \ No newline at end of file +class C3 implements boolean { } + +const C4 = class implements number {} +const C5 = class implements string {} +const C6 = class implements boolean {} + +const C7 = class A implements number { } +const C8 = class B implements string { } +const C9 = class C implements boolean { } diff --git a/tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingPrimitive.ts b/tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingPrimitive.ts index aaffa1a9dbf88..92b6641cd60db 100644 --- a/tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingPrimitive.ts +++ b/tests/cases/conformance/classes/classDeclarations/classHeritageSpecification/classExtendingPrimitive.ts @@ -11,4 +11,12 @@ class C6 extends undefined { } class C7 extends Undefined { } enum E { A } -class C8 extends E { } \ No newline at end of file +class C8 extends E { } + +const C9 = class extends number { } +const C10 = class extends string { } +const C11 = class extends boolean { } + +const C12 = class A extends number { } +const C13 = class B extends string { } +const C14 = class C extends boolean { }