Skip to content

Commit

Permalink
fix(60484): Implementing a prim type in a class expression should rep…
Browse files Browse the repository at this point in the history
…ort error (#60490)
  • Loading branch information
a-tarasyuk authored Nov 20, 2024
1 parent d6b7c41 commit d85767a
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
Expand Down
31 changes: 29 additions & 2 deletions tests/baselines/reference/classExtendingPrimitive.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 { }
Expand Down Expand Up @@ -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.
!!! 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.

53 changes: 52 additions & 1 deletion tests/baselines/reference/classExtendingPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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));
21 changes: 21 additions & 0 deletions tests/baselines/reference/classExtendingPrimitive.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -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))

54 changes: 54 additions & 0 deletions tests/baselines/reference/classExtendingPrimitive.types
Original file line number Diff line number Diff line change
Expand Up @@ -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
> : ^^^

31 changes: 29 additions & 2 deletions tests/baselines/reference/classImplementsPrimitive.errors.txt
Original file line number Diff line number Diff line change
@@ -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 { }
Expand All @@ -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.
!!! 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.

41 changes: 40 additions & 1 deletion tests/baselines/reference/classImplementsPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}());
21 changes: 21 additions & 0 deletions tests/baselines/reference/classImplementsPrimitive.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -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))

42 changes: 42 additions & 0 deletions tests/baselines/reference/classImplementsPrimitive.types
Original file line number Diff line number Diff line change
Expand Up @@ -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
> : ^^^^^^^^

10 changes: 9 additions & 1 deletion tests/cases/compiler/classImplementsPrimitive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@

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 { }
Loading

0 comments on commit d85767a

Please sign in to comment.