From f4705246a258feaf6fb95bff0d2b2be6096f850b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 17 Oct 2025 23:35:27 +0200 Subject: [PATCH 1/6] Fixed crash when using intersection with private constructors as a base class --- src/compiler/checker.ts | 20 ++- .../extendPrivateConstructorClass2.errors.txt | 71 ++++++++ .../extendPrivateConstructorClass2.symbols | 104 ++++++++++++ .../extendPrivateConstructorClass2.types | 153 ++++++++++++++++++ .../extendPrivateConstructorClass2.ts | 49 ++++++ 5 files changed, 389 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/extendPrivateConstructorClass2.errors.txt create mode 100644 tests/baselines/reference/extendPrivateConstructorClass2.symbols create mode 100644 tests/baselines/reference/extendPrivateConstructorClass2.types create mode 100644 tests/cases/compiler/extendPrivateConstructorClass2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48bc0da113816..582cdc04e3108 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28402,6 +28402,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type.flags & TypeFlags.Union ? every((type as UnionType).types, f) : f(type); } + function someContainedType(type: Type, f: (t: Type) => boolean): boolean { + return type.flags & TypeFlags.UnionOrIntersection ? some((type as UnionOrIntersectionType).types, f) : f(type); + } + function everyContainedType(type: Type, f: (t: Type) => boolean): boolean { return type.flags & TypeFlags.UnionOrIntersection ? every((type as UnionOrIntersectionType).types, f) : f(type); } @@ -47349,14 +47353,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) { const signatures = getSignaturesOfType(type, SignatureKind.Construct); - if (signatures.length) { - const declaration = signatures[0].declaration; - if (declaration && hasEffectiveModifier(declaration, ModifierFlags.Private)) { - const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol)!; - if (!isNodeWithinClass(node, typeClassDeclaration)) { - error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); - } - } + const isPrivateAccessOutsideOfClass = some(signatures, (s) => + !!s.declaration && hasEffectiveModifier(s.declaration, ModifierFlags.Private) && + someContainedType(type, (t) => { + const typeClassDeclaration = getClassLikeDeclarationOfSymbol(t.symbol); + return !!typeClassDeclaration && !isNodeWithinClass(node, typeClassDeclaration); + })); + if (isPrivateAccessOutsideOfClass) { + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, type.symbol ? getFullyQualifiedName(type.symbol) : typeToString(type)); } } diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt new file mode 100644 index 0000000000000..7926be1f167ae --- /dev/null +++ b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt @@ -0,0 +1,71 @@ +extendPrivateConstructorClass2.ts(10,1): error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. +extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'typeof j1 & typeof j2'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(44,5): error TS1184: Modifiers cannot appear here. +extendPrivateConstructorClass2.ts(44,30): error TS2510: Base constructors must all have the same return type. +extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'typeof j3 & typeof j4'. Class constructor is marked as private. + + +==== extendPrivateConstructorClass2.ts (7 errors) ==== + class A1 { + private constructor(arg: string) {} + } + class B1 { + constructor(arg: number) {} + } + + declare const Cls1: typeof A1 & typeof B1; + + new Cls1(42); // error + ~~~~~~~~~~~~ +!!! error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. + class Derived1 extends Cls1 {} // error + ~~~~ +!!! error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. + + class A2 { + constructor(arg: string) {} + } + class B2 { + private constructor(arg: number) {} + } + + declare const Cls2: typeof A2 & typeof B2; + + new Cls2(42); // error + class Derived2 extends Cls2 {} // error + ~~~~ +!!! error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. + + // https://github.com/microsoft/TypeScript/issues/62614 + declare abstract class j1 { + private constructor(...args: any[]); + } + declare abstract class j2 { + private constructor(...args: any[]); + } + declare const jS: typeof j1 & typeof j2; + declare class j0 extends jS {} // error + ~~ +!!! error TS2675: Cannot extend a class 'typeof j1 & typeof j2'. Class constructor is marked as private. + + abstract class j3 { + private constructor(arg: number) {} + method(_any: any) { + abstract class j4 { + private constructor(arg: number) {} + } + + const jS: typeof j3 & typeof j4 = _any; + + declare class j0 extends jS {} // bizarre but ok + ~~~~~~~ +!!! error TS1184: Modifiers cannot appear here. + ~~ +!!! error TS2510: Base constructors must all have the same return type. + ~~ +!!! error TS2675: Cannot extend a class 'typeof j3 & typeof j4'. Class constructor is marked as private. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.symbols b/tests/baselines/reference/extendPrivateConstructorClass2.symbols new file mode 100644 index 0000000000000..2664854503c78 --- /dev/null +++ b/tests/baselines/reference/extendPrivateConstructorClass2.symbols @@ -0,0 +1,104 @@ +//// [tests/cases/compiler/extendPrivateConstructorClass2.ts] //// + +=== extendPrivateConstructorClass2.ts === +class A1 { +>A1 : Symbol(A1, Decl(extendPrivateConstructorClass2.ts, 0, 0)) + + private constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 1, 22)) +} +class B1 { +>B1 : Symbol(B1, Decl(extendPrivateConstructorClass2.ts, 2, 1)) + + constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 4, 14)) +} + +declare const Cls1: typeof A1 & typeof B1; +>Cls1 : Symbol(Cls1, Decl(extendPrivateConstructorClass2.ts, 7, 13)) +>A1 : Symbol(A1, Decl(extendPrivateConstructorClass2.ts, 0, 0)) +>B1 : Symbol(B1, Decl(extendPrivateConstructorClass2.ts, 2, 1)) + +new Cls1(42); // error +>Cls1 : Symbol(Cls1, Decl(extendPrivateConstructorClass2.ts, 7, 13)) + +class Derived1 extends Cls1 {} // error +>Derived1 : Symbol(Derived1, Decl(extendPrivateConstructorClass2.ts, 9, 13)) +>Cls1 : Symbol(Cls1, Decl(extendPrivateConstructorClass2.ts, 7, 13)) + +class A2 { +>A2 : Symbol(A2, Decl(extendPrivateConstructorClass2.ts, 10, 30)) + + constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 13, 14)) +} +class B2 { +>B2 : Symbol(B2, Decl(extendPrivateConstructorClass2.ts, 14, 1)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 16, 22)) +} + +declare const Cls2: typeof A2 & typeof B2; +>Cls2 : Symbol(Cls2, Decl(extendPrivateConstructorClass2.ts, 19, 13)) +>A2 : Symbol(A2, Decl(extendPrivateConstructorClass2.ts, 10, 30)) +>B2 : Symbol(B2, Decl(extendPrivateConstructorClass2.ts, 14, 1)) + +new Cls2(42); // error +>Cls2 : Symbol(Cls2, Decl(extendPrivateConstructorClass2.ts, 19, 13)) + +class Derived2 extends Cls2 {} // error +>Derived2 : Symbol(Derived2, Decl(extendPrivateConstructorClass2.ts, 21, 13)) +>Cls2 : Symbol(Cls2, Decl(extendPrivateConstructorClass2.ts, 19, 13)) + +// https://github.com/microsoft/TypeScript/issues/62614 +declare abstract class j1 { +>j1 : Symbol(j1, Decl(extendPrivateConstructorClass2.ts, 22, 30)) + + private constructor(...args: any[]); +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 26, 22)) +} +declare abstract class j2 { +>j2 : Symbol(j2, Decl(extendPrivateConstructorClass2.ts, 27, 1)) + + private constructor(...args: any[]); +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 29, 22)) +} +declare const jS: typeof j1 & typeof j2; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 31, 13)) +>j1 : Symbol(j1, Decl(extendPrivateConstructorClass2.ts, 22, 30)) +>j2 : Symbol(j2, Decl(extendPrivateConstructorClass2.ts, 27, 1)) + +declare class j0 extends jS {} // error +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 31, 40)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 31, 13)) + +abstract class j3 { +>j3 : Symbol(j3, Decl(extendPrivateConstructorClass2.ts, 32, 30)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 35, 22)) + + method(_any: any) { +>method : Symbol(j3.method, Decl(extendPrivateConstructorClass2.ts, 35, 37)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 36, 9)) + + abstract class j4 { +>j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 21)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 38, 26)) + } + + const jS: typeof j3 & typeof j4 = _any; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 41, 9)) +>j3 : Symbol(j3, Decl(extendPrivateConstructorClass2.ts, 32, 30)) +>j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 21)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 36, 9)) + + declare class j0 extends jS {} // bizarre but ok +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 41, 43)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 41, 9)) + } +} + diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.types b/tests/baselines/reference/extendPrivateConstructorClass2.types new file mode 100644 index 0000000000000..0170594e19813 --- /dev/null +++ b/tests/baselines/reference/extendPrivateConstructorClass2.types @@ -0,0 +1,153 @@ +//// [tests/cases/compiler/extendPrivateConstructorClass2.ts] //// + +=== extendPrivateConstructorClass2.ts === +class A1 { +>A1 : A1 +> : ^^ + + private constructor(arg: string) {} +>arg : string +> : ^^^^^^ +} +class B1 { +>B1 : B1 +> : ^^ + + constructor(arg: number) {} +>arg : number +> : ^^^^^^ +} + +declare const Cls1: typeof A1 & typeof B1; +>Cls1 : typeof A1 & typeof B1 +> : ^^^^^^^^^^^^^^^^^^^^^ +>A1 : typeof A1 +> : ^^^^^^^^^ +>B1 : typeof B1 +> : ^^^^^^^^^ + +new Cls1(42); // error +>new Cls1(42) : any +> : ^^^ +>Cls1 : typeof A1 & typeof B1 +> : ^^^^^^^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + +class Derived1 extends Cls1 {} // error +>Derived1 : Derived1 +> : ^^^^^^^^ +>Cls1 : A1 +> : ^^ + +class A2 { +>A2 : A2 +> : ^^ + + constructor(arg: string) {} +>arg : string +> : ^^^^^^ +} +class B2 { +>B2 : B2 +> : ^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ +} + +declare const Cls2: typeof A2 & typeof B2; +>Cls2 : typeof A2 & typeof B2 +> : ^^^^^^^^^^^^^^^^^^^^^ +>A2 : typeof A2 +> : ^^^^^^^^^ +>B2 : typeof B2 +> : ^^^^^^^^^ + +new Cls2(42); // error +>new Cls2(42) : B2 +> : ^^ +>Cls2 : typeof A2 & typeof B2 +> : ^^^^^^^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + +class Derived2 extends Cls2 {} // error +>Derived2 : Derived2 +> : ^^^^^^^^ +>Cls2 : A2 +> : ^^ + +// https://github.com/microsoft/TypeScript/issues/62614 +declare abstract class j1 { +>j1 : j1 +> : ^^ + + private constructor(...args: any[]); +>args : any[] +> : ^^^^^ +} +declare abstract class j2 { +>j2 : j2 +> : ^^ + + private constructor(...args: any[]); +>args : any[] +> : ^^^^^ +} +declare const jS: typeof j1 & typeof j2; +>jS : typeof j1 & typeof j2 +> : ^^^^^^^^^^^^^^^^^^^^^ +>j1 : typeof j1 +> : ^^^^^^^^^ +>j2 : typeof j2 +> : ^^^^^^^^^ + +declare class j0 extends jS {} // error +>j0 : j0 +> : ^^ +>jS : j1 & j2 +> : ^^^^^^^ + +abstract class j3 { +>j3 : j3 +> : ^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + + method(_any: any) { +>method : (_any: any) => void +> : ^ ^^ ^^^^^^^^^ +>_any : any +> : ^^^ + + abstract class j4 { +>j4 : j4 +> : ^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + } + + const jS: typeof j3 & typeof j4 = _any; +>jS : typeof j3 & typeof j4 +> : ^^^^^^^^^^^^^^^^^^^^^ +>j3 : typeof j3 +> : ^^^^^^^^^ +>j4 : typeof j4 +> : ^^^^^^^^^ +>_any : any +> : ^^^ + + declare class j0 extends jS {} // bizarre but ok +>j0 : j0 +> : ^^ +>jS : j3 +> : ^^ + } +} + diff --git a/tests/cases/compiler/extendPrivateConstructorClass2.ts b/tests/cases/compiler/extendPrivateConstructorClass2.ts new file mode 100644 index 0000000000000..6057df765331b --- /dev/null +++ b/tests/cases/compiler/extendPrivateConstructorClass2.ts @@ -0,0 +1,49 @@ +// @strict: true +// @noEmit: true + +class A1 { + private constructor(arg: string) {} +} +class B1 { + constructor(arg: number) {} +} + +declare const Cls1: typeof A1 & typeof B1; + +new Cls1(42); // error +class Derived1 extends Cls1 {} // error + +class A2 { + constructor(arg: string) {} +} +class B2 { + private constructor(arg: number) {} +} + +declare const Cls2: typeof A2 & typeof B2; + +new Cls2(42); // error +class Derived2 extends Cls2 {} // error + +// https://github.com/microsoft/TypeScript/issues/62614 +declare abstract class j1 { + private constructor(...args: any[]); +} +declare abstract class j2 { + private constructor(...args: any[]); +} +declare const jS: typeof j1 & typeof j2; +declare class j0 extends jS {} // error + +abstract class j3 { + private constructor(arg: number) {} + method(_any: any) { + abstract class j4 { + private constructor(arg: number) {} + } + + const jS: typeof j3 & typeof j4 = _any; + + declare class j0 extends jS {} // bizarre but ok + } +} From 74a85326ded265d4ac5072959f3069cd18dce350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 17 Oct 2025 23:36:08 +0200 Subject: [PATCH 2/6] fix an extra thing --- src/compiler/checker.ts | 72 ++++++++----------- .../classConstructorAccessibility.errors.txt | 8 +-- .../extendPrivateConstructorClass2.errors.txt | 9 ++- .../extendPrivateConstructorClass2.types | 4 +- .../reference/noCrashOnMixin.errors.txt | 4 +- 5 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 582cdc04e3108..b2c5978fdfa0d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28402,10 +28402,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type.flags & TypeFlags.Union ? every((type as UnionType).types, f) : f(type); } - function someContainedType(type: Type, f: (t: Type) => boolean): boolean { - return type.flags & TypeFlags.UnionOrIntersection ? some((type as UnionOrIntersectionType).types, f) : f(type); - } - function everyContainedType(type: Type, f: (t: Type) => boolean): boolean { return type.flags & TypeFlags.UnionOrIntersection ? every((type as UnionOrIntersectionType).types, f) : f(type); } @@ -37060,7 +37056,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that the user will not add any. const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct); if (constructSignatures.length) { - if (!isConstructorAccessible(node, constructSignatures[0])) { + const accessibilityErrorKind = getConstructorAccessibilityError(node, constructSignatures, ModifierFlags.NonPublicAccessibilityModifier); + if (accessibilityErrorKind) { + if (accessibilityErrorKind & ModifierFlags.Private) { + error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, expressionType.symbol ? getFullyQualifiedName(expressionType.symbol) : typeToString(expressionType)); + } + if (accessibilityErrorKind & ModifierFlags.Protected) { + error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, expressionType.symbol ? getFullyQualifiedName(expressionType.symbol) : typeToString(expressionType)); + } return resolveErrorCall(node); } // If the expression is a class of abstract type, or an abstract construct signature, @@ -37141,41 +37144,34 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return typeHasProtectedAccessibleBase(target, firstBase as InterfaceType); } - function isConstructorAccessible(node: NewExpression, signature: Signature) { - if (!signature || !signature.declaration) { - return true; - } - - const declaration = signature.declaration; - const modifiers = getSelectedEffectiveModifierFlags(declaration, ModifierFlags.NonPublicAccessibilityModifier); + function getConstructorAccessibilityErrorKind(node: Expression, signatures: readonly Signature[], modifiersMask: ModifierFlags) { + for (const signature of signatures) { + if (!signature.declaration) { + continue; + } + const declaration = signature.declaration; + const modifiers = getSelectedEffectiveModifierFlags(declaration, modifiersMask); - // (1) Public constructors and (2) constructor functions are always accessible. - if (!modifiers || declaration.kind !== SyntaxKind.Constructor) { - return true; - } + // (1) Public constructors and (2) constructor functions are always accessible. + if (!modifiers || declaration.kind !== SyntaxKind.Constructor) { + continue; + } - const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!; - const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol) as InterfaceType; + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!; - // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) - if (!isNodeWithinClass(node, declaringClassDeclaration)) { - const containingClass = getContainingClass(node); - if (containingClass && modifiers & ModifierFlags.Protected) { - const containingType = getTypeOfNode(containingClass); - if (typeHasProtectedAccessibleBase(declaration.parent.symbol, containingType as InterfaceType)) { - return true; + // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) + if (!isNodeWithinClass(node, declaringClassDeclaration)) { + const containingClass = getContainingClass(node); + if (containingClass && modifiers & ModifierFlags.Protected) { + const containingType = getTypeOfNode(containingClass); + if (typeHasProtectedAccessibleBase(declaration.parent.symbol, containingType as InterfaceType)) { + continue; + } } + return modifiers; } - if (modifiers & ModifierFlags.Private) { - error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); - } - if (modifiers & ModifierFlags.Protected) { - error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); - } - return false; } - - return true; + return ModifierFlags.None; } function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain; relatedMessage: DiagnosticMessage | undefined; } { @@ -47353,13 +47349,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) { const signatures = getSignaturesOfType(type, SignatureKind.Construct); - const isPrivateAccessOutsideOfClass = some(signatures, (s) => - !!s.declaration && hasEffectiveModifier(s.declaration, ModifierFlags.Private) && - someContainedType(type, (t) => { - const typeClassDeclaration = getClassLikeDeclarationOfSymbol(t.symbol); - return !!typeClassDeclaration && !isNodeWithinClass(node, typeClassDeclaration); - })); - if (isPrivateAccessOutsideOfClass) { + if (getConstructorAccessibilityErrorKind(node, signatures, ModifierFlags.Private)) { error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, type.symbol ? getFullyQualifiedName(type.symbol) : typeToString(type)); } } diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index d3e2ba69434a1..1ad858d234702 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -1,7 +1,7 @@ classConstructorAccessibility.ts(14,9): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. classConstructorAccessibility.ts(15,9): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. -classConstructorAccessibility.ts(31,13): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. -classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. +classConstructorAccessibility.ts(31,13): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. +classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. ==== classConstructorAccessibility.ts (4 errors) ==== @@ -41,9 +41,9 @@ classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' is private and only accessible within the class declaration. +!!! error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. var e = new E(1); // error ~~~~~~~~ -!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. +!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. } \ No newline at end of file diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt index 7926be1f167ae..514d4063b355f 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt +++ b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt @@ -1,5 +1,6 @@ -extendPrivateConstructorClass2.ts(10,1): error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. +extendPrivateConstructorClass2.ts(10,1): error TS2673: Constructor of class 'typeof A1 & typeof B1' is private and only accessible within the class declaration. extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(22,1): error TS2673: Constructor of class 'typeof A2 & typeof B2' is private and only accessible within the class declaration. extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'typeof j1 & typeof j2'. Class constructor is marked as private. extendPrivateConstructorClass2.ts(44,5): error TS1184: Modifiers cannot appear here. @@ -7,7 +8,7 @@ extendPrivateConstructorClass2.ts(44,30): error TS2510: Base constructors must a extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'typeof j3 & typeof j4'. Class constructor is marked as private. -==== extendPrivateConstructorClass2.ts (7 errors) ==== +==== extendPrivateConstructorClass2.ts (8 errors) ==== class A1 { private constructor(arg: string) {} } @@ -19,7 +20,7 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't new Cls1(42); // error ~~~~~~~~~~~~ -!!! error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. +!!! error TS2673: Constructor of class 'typeof A1 & typeof B1' is private and only accessible within the class declaration. class Derived1 extends Cls1 {} // error ~~~~ !!! error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. @@ -34,6 +35,8 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't declare const Cls2: typeof A2 & typeof B2; new Cls2(42); // error + ~~~~~~~~~~~~ +!!! error TS2673: Constructor of class 'typeof A2 & typeof B2' is private and only accessible within the class declaration. class Derived2 extends Cls2 {} // error ~~~~ !!! error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.types b/tests/baselines/reference/extendPrivateConstructorClass2.types index 0170594e19813..d667b5b0665c2 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.types +++ b/tests/baselines/reference/extendPrivateConstructorClass2.types @@ -66,8 +66,8 @@ declare const Cls2: typeof A2 & typeof B2; > : ^^^^^^^^^ new Cls2(42); // error ->new Cls2(42) : B2 -> : ^^ +>new Cls2(42) : any +> : ^^^ >Cls2 : typeof A2 & typeof B2 > : ^^^^^^^^^^^^^^^^^^^^^ >42 : 42 diff --git a/tests/baselines/reference/noCrashOnMixin.errors.txt b/tests/baselines/reference/noCrashOnMixin.errors.txt index cf9bb9cd07499..9023d324c25c8 100644 --- a/tests/baselines/reference/noCrashOnMixin.errors.txt +++ b/tests/baselines/reference/noCrashOnMixin.errors.txt @@ -1,4 +1,4 @@ -noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration. +noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Concrete' is protected and only accessible within the class declaration. ==== noCrashOnMixin.ts (1 errors) ==== @@ -24,6 +24,6 @@ noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Abstract' is protec public trigger() { new Concrete(); ~~~~~~~~~~~~~~ -!!! error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration. +!!! error TS2674: Constructor of class 'Concrete' is protected and only accessible within the class declaration. } } \ No newline at end of file From 80647a81d15bef1eaecd273e6f06eb57fd3b6d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 17 Oct 2025 23:36:42 +0200 Subject: [PATCH 3/6] fix reported classes in error messages --- src/compiler/checker.ts | 26 +++++++++++-------- .../classConstructorAccessibility.errors.txt | 8 +++--- .../extendPrivateConstructorClass2.errors.txt | 24 ++++++++--------- .../reference/noCrashOnMixin.errors.txt | 4 +-- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b2c5978fdfa0d..af7df91221824 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37056,13 +37056,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // that the user will not add any. const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct); if (constructSignatures.length) { - const accessibilityErrorKind = getConstructorAccessibilityError(node, constructSignatures, ModifierFlags.NonPublicAccessibilityModifier); - if (accessibilityErrorKind) { - if (accessibilityErrorKind & ModifierFlags.Private) { - error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, expressionType.symbol ? getFullyQualifiedName(expressionType.symbol) : typeToString(expressionType)); + const accessibilityError = getConstructorAccessibilityError(node, constructSignatures, ModifierFlags.NonPublicAccessibilityModifier); + if (accessibilityError) { + if (accessibilityError.kind & ModifierFlags.Private) { + error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(accessibilityError.declaringClass)); } - if (accessibilityErrorKind & ModifierFlags.Protected) { - error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, expressionType.symbol ? getFullyQualifiedName(expressionType.symbol) : typeToString(expressionType)); + if (accessibilityError.kind & ModifierFlags.Protected) { + error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(accessibilityError.declaringClass)); } return resolveErrorCall(node); } @@ -37144,7 +37144,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return typeHasProtectedAccessibleBase(target, firstBase as InterfaceType); } - function getConstructorAccessibilityErrorKind(node: Expression, signatures: readonly Signature[], modifiersMask: ModifierFlags) { + function getConstructorAccessibilityError(node: Expression, signatures: readonly Signature[], modifiersMask: ModifierFlags) { for (const signature of signatures) { if (!signature.declaration) { continue; @@ -37168,10 +37168,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { continue; } } - return modifiers; + return { + kind: modifiers, + declaringClass: getDeclaredTypeOfSymbol(declaration.parent.symbol), + } } } - return ModifierFlags.None; + return undefined; } function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain; relatedMessage: DiagnosticMessage | undefined; } { @@ -47349,8 +47352,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) { const signatures = getSignaturesOfType(type, SignatureKind.Construct); - if (getConstructorAccessibilityErrorKind(node, signatures, ModifierFlags.Private)) { - error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, type.symbol ? getFullyQualifiedName(type.symbol) : typeToString(type)); + const accessibilityError = getConstructorAccessibilityError(node, signatures, ModifierFlags.Private); + if (accessibilityError) { + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(accessibilityError.declaringClass.symbol)); } } diff --git a/tests/baselines/reference/classConstructorAccessibility.errors.txt b/tests/baselines/reference/classConstructorAccessibility.errors.txt index 1ad858d234702..d3e2ba69434a1 100644 --- a/tests/baselines/reference/classConstructorAccessibility.errors.txt +++ b/tests/baselines/reference/classConstructorAccessibility.errors.txt @@ -1,7 +1,7 @@ classConstructorAccessibility.ts(14,9): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. classConstructorAccessibility.ts(15,9): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. -classConstructorAccessibility.ts(31,13): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. -classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. +classConstructorAccessibility.ts(31,13): error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. +classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. ==== classConstructorAccessibility.ts (4 errors) ==== @@ -41,9 +41,9 @@ classConstructorAccessibility.ts(32,13): error TS2674: Constructor of class 'E' var c = new C(1); var d = new D(1); // error ~~~~~~~~ -!!! error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. +!!! error TS2673: Constructor of class 'D' is private and only accessible within the class declaration. var e = new E(1); // error ~~~~~~~~ -!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. +!!! error TS2674: Constructor of class 'E' is protected and only accessible within the class declaration. } \ No newline at end of file diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt index 514d4063b355f..1a8c4b60f98be 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt +++ b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt @@ -1,11 +1,11 @@ -extendPrivateConstructorClass2.ts(10,1): error TS2673: Constructor of class 'typeof A1 & typeof B1' is private and only accessible within the class declaration. -extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. -extendPrivateConstructorClass2.ts(22,1): error TS2673: Constructor of class 'typeof A2 & typeof B2' is private and only accessible within the class declaration. -extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. -extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'typeof j1 & typeof j2'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(10,1): error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. +extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'A1'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(22,1): error TS2673: Constructor of class 'B2' is private and only accessible within the class declaration. +extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'B2'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j1'. Class constructor is marked as private. extendPrivateConstructorClass2.ts(44,5): error TS1184: Modifiers cannot appear here. extendPrivateConstructorClass2.ts(44,30): error TS2510: Base constructors must all have the same return type. -extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'typeof j3 & typeof j4'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'j4'. Class constructor is marked as private. ==== extendPrivateConstructorClass2.ts (8 errors) ==== @@ -20,10 +20,10 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't new Cls1(42); // error ~~~~~~~~~~~~ -!!! error TS2673: Constructor of class 'typeof A1 & typeof B1' is private and only accessible within the class declaration. +!!! error TS2673: Constructor of class 'A1' is private and only accessible within the class declaration. class Derived1 extends Cls1 {} // error ~~~~ -!!! error TS2675: Cannot extend a class 'typeof A1 & typeof B1'. Class constructor is marked as private. +!!! error TS2675: Cannot extend a class 'A1'. Class constructor is marked as private. class A2 { constructor(arg: string) {} @@ -36,10 +36,10 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't new Cls2(42); // error ~~~~~~~~~~~~ -!!! error TS2673: Constructor of class 'typeof A2 & typeof B2' is private and only accessible within the class declaration. +!!! error TS2673: Constructor of class 'B2' is private and only accessible within the class declaration. class Derived2 extends Cls2 {} // error ~~~~ -!!! error TS2675: Cannot extend a class 'typeof A2 & typeof B2'. Class constructor is marked as private. +!!! error TS2675: Cannot extend a class 'B2'. Class constructor is marked as private. // https://github.com/microsoft/TypeScript/issues/62614 declare abstract class j1 { @@ -51,7 +51,7 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't declare const jS: typeof j1 & typeof j2; declare class j0 extends jS {} // error ~~ -!!! error TS2675: Cannot extend a class 'typeof j1 & typeof j2'. Class constructor is marked as private. +!!! error TS2675: Cannot extend a class 'j1'. Class constructor is marked as private. abstract class j3 { private constructor(arg: number) {} @@ -68,7 +68,7 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 't ~~ !!! error TS2510: Base constructors must all have the same return type. ~~ -!!! error TS2675: Cannot extend a class 'typeof j3 & typeof j4'. Class constructor is marked as private. +!!! error TS2675: Cannot extend a class 'j4'. Class constructor is marked as private. } } \ No newline at end of file diff --git a/tests/baselines/reference/noCrashOnMixin.errors.txt b/tests/baselines/reference/noCrashOnMixin.errors.txt index 9023d324c25c8..cf9bb9cd07499 100644 --- a/tests/baselines/reference/noCrashOnMixin.errors.txt +++ b/tests/baselines/reference/noCrashOnMixin.errors.txt @@ -1,4 +1,4 @@ -noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Concrete' is protected and only accessible within the class declaration. +noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration. ==== noCrashOnMixin.ts (1 errors) ==== @@ -24,6 +24,6 @@ noCrashOnMixin.ts(21,9): error TS2674: Constructor of class 'Concrete' is protec public trigger() { new Concrete(); ~~~~~~~~~~~~~~ -!!! error TS2674: Constructor of class 'Concrete' is protected and only accessible within the class declaration. +!!! error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration. } } \ No newline at end of file From a3add66226192ac0b38396891163c71f75a72966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 17 Oct 2025 23:48:30 +0200 Subject: [PATCH 4/6] tweak tests --- .../extendPrivateConstructorClass2.errors.txt | 43 +++++--- .../extendPrivateConstructorClass2.symbols | 83 +++++++++++++--- .../extendPrivateConstructorClass2.types | 99 ++++++++++++++++--- .../extendPrivateConstructorClass2.ts | 32 +++++- 4 files changed, 206 insertions(+), 51 deletions(-) diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt index 1a8c4b60f98be..e630f98a03273 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt +++ b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt @@ -3,12 +3,9 @@ extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'A extendPrivateConstructorClass2.ts(22,1): error TS2673: Constructor of class 'B2' is private and only accessible within the class declaration. extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'B2'. Class constructor is marked as private. extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j1'. Class constructor is marked as private. -extendPrivateConstructorClass2.ts(44,5): error TS1184: Modifiers cannot appear here. -extendPrivateConstructorClass2.ts(44,30): error TS2510: Base constructors must all have the same return type. -extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'j4'. Class constructor is marked as private. -==== extendPrivateConstructorClass2.ts (8 errors) ==== +==== extendPrivateConstructorClass2.ts (5 errors) ==== class A1 { private constructor(arg: string) {} } @@ -54,21 +51,37 @@ extendPrivateConstructorClass2.ts(44,30): error TS2675: Cannot extend a class 'j !!! error TS2675: Cannot extend a class 'j1'. Class constructor is marked as private. abstract class j3 { - private constructor(arg: number) {} - method(_any: any) { + private constructor(...args: any[]) {} + method1() { abstract class j4 { - private constructor(arg: number) {} + private constructor(...args: any[]) {} + method2(_any: any) { + const jS: typeof j3 & typeof j4 = _any; + + // bizarre but ok + class j0 extends jS { + method1() {} + method2() {} + } + } } + } + } - const jS: typeof j3 & typeof j4 = _any; + abstract class j5 { + private constructor(...args: any[]) {} + method1(_any: any) { + abstract class j6 { + private constructor(...args: any[]) {} + method2() {} + } + const jS: typeof j5 & typeof j6 = _any; - declare class j0 extends jS {} // bizarre but ok - ~~~~~~~ -!!! error TS1184: Modifiers cannot appear here. - ~~ -!!! error TS2510: Base constructors must all have the same return type. - ~~ -!!! error TS2675: Cannot extend a class 'j4'. Class constructor is marked as private. + // bizarre but ok too given the base is a result of a mixin + class j0 extends jS { + method1() {} + method2() {} + } } } \ No newline at end of file diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.symbols b/tests/baselines/reference/extendPrivateConstructorClass2.symbols index 2664854503c78..e33455fafbb50 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.symbols +++ b/tests/baselines/reference/extendPrivateConstructorClass2.symbols @@ -76,29 +76,80 @@ declare class j0 extends jS {} // error abstract class j3 { >j3 : Symbol(j3, Decl(extendPrivateConstructorClass2.ts, 32, 30)) - private constructor(arg: number) {} ->arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 35, 22)) + private constructor(...args: any[]) {} +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 35, 22)) - method(_any: any) { ->method : Symbol(j3.method, Decl(extendPrivateConstructorClass2.ts, 35, 37)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 36, 9)) + method1() { +>method1 : Symbol(j3.method1, Decl(extendPrivateConstructorClass2.ts, 35, 40)) abstract class j4 { ->j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 21)) +>j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 13)) - private constructor(arg: number) {} ->arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 38, 26)) - } + private constructor(...args: any[]) {} +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 38, 26)) - const jS: typeof j3 & typeof j4 = _any; ->jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 41, 9)) + method2(_any: any) { +>method2 : Symbol(j4.method2, Decl(extendPrivateConstructorClass2.ts, 38, 44)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 39, 14)) + + const jS: typeof j3 & typeof j4 = _any; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 40, 13)) >j3 : Symbol(j3, Decl(extendPrivateConstructorClass2.ts, 32, 30)) ->j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 21)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 36, 9)) +>j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 13)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 39, 14)) + + // bizarre but ok + class j0 extends jS { +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 40, 47)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 40, 13)) + + method1() {} +>method1 : Symbol(j0.method1, Decl(extendPrivateConstructorClass2.ts, 43, 29)) + + method2() {} +>method2 : Symbol(j0.method2, Decl(extendPrivateConstructorClass2.ts, 44, 22)) + } + } + } + } +} + +abstract class j5 { +>j5 : Symbol(j5, Decl(extendPrivateConstructorClass2.ts, 50, 1)) + + private constructor(...args: any[]) {} +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 53, 22)) + + method1(_any: any) { +>method1 : Symbol(j5.method1, Decl(extendPrivateConstructorClass2.ts, 53, 40)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 54, 10)) - declare class j0 extends jS {} // bizarre but ok ->j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 41, 43)) ->jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 41, 9)) + abstract class j6 { +>j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 22)) + + private constructor(...args: any[]) {} +>args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 56, 26)) + + method2() {} +>method2 : Symbol(j6.method2, Decl(extendPrivateConstructorClass2.ts, 56, 44)) + } + const jS: typeof j5 & typeof j6 = _any; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 59, 9)) +>j5 : Symbol(j5, Decl(extendPrivateConstructorClass2.ts, 50, 1)) +>j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 22)) +>_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 54, 10)) + + // bizarre but ok too given the base is a result of a mixin + class j0 extends jS { +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 59, 43)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 59, 9)) + + method1() {} +>method1 : Symbol(j0.method1, Decl(extendPrivateConstructorClass2.ts, 62, 25)) + + method2() {} +>method2 : Symbol(j0.method2, Decl(extendPrivateConstructorClass2.ts, 63, 18)) + } } } diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.types b/tests/baselines/reference/extendPrivateConstructorClass2.types index d667b5b0665c2..288803e0b0f75 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.types +++ b/tests/baselines/reference/extendPrivateConstructorClass2.types @@ -114,26 +114,29 @@ abstract class j3 { >j3 : j3 > : ^^ - private constructor(arg: number) {} ->arg : number -> : ^^^^^^ + private constructor(...args: any[]) {} +>args : any[] +> : ^^^^^ - method(_any: any) { ->method : (_any: any) => void -> : ^ ^^ ^^^^^^^^^ ->_any : any -> : ^^^ + method1() { +>method1 : () => void +> : ^^^^^^^^^^ abstract class j4 { >j4 : j4 > : ^^ - private constructor(arg: number) {} ->arg : number -> : ^^^^^^ - } + private constructor(...args: any[]) {} +>args : any[] +> : ^^^^^ - const jS: typeof j3 & typeof j4 = _any; + method2(_any: any) { +>method2 : (_any: any) => void +> : ^ ^^ ^^^^^^^^^ +>_any : any +> : ^^^ + + const jS: typeof j3 & typeof j4 = _any; >jS : typeof j3 & typeof j4 > : ^^^^^^^^^^^^^^^^^^^^^ >j3 : typeof j3 @@ -143,11 +146,77 @@ abstract class j3 { >_any : any > : ^^^ - declare class j0 extends jS {} // bizarre but ok + // bizarre but ok + class j0 extends jS { >j0 : j0 > : ^^ ->jS : j3 +>jS : j3 & j4 +> : ^^^^^^^ + + method1() {} +>method1 : () => void +> : ^^^^^^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } + } + } + } +} + +abstract class j5 { +>j5 : j5 > : ^^ + + private constructor(...args: any[]) {} +>args : any[] +> : ^^^^^ + + method1(_any: any) { +>method1 : (_any: any) => void +> : ^ ^^ ^^^^^^^^^ +>_any : any +> : ^^^ + + abstract class j6 { +>j6 : j6 +> : ^^ + + private constructor(...args: any[]) {} +>args : any[] +> : ^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } + const jS: typeof j5 & typeof j6 = _any; +>jS : typeof j5 & typeof j6 +> : ^^^^^^^^^^^^^^^^^^^^^ +>j5 : typeof j5 +> : ^^^^^^^^^ +>j6 : typeof j6 +> : ^^^^^^^^^ +>_any : any +> : ^^^ + + // bizarre but ok too given the base is a result of a mixin + class j0 extends jS { +>j0 : j0 +> : ^^ +>jS : j5 & j6 +> : ^^^^^^^ + + method1() {} +>method1 : () => void +> : ^^^^^^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } } } diff --git a/tests/cases/compiler/extendPrivateConstructorClass2.ts b/tests/cases/compiler/extendPrivateConstructorClass2.ts index 6057df765331b..9e060cbdb29f3 100644 --- a/tests/cases/compiler/extendPrivateConstructorClass2.ts +++ b/tests/cases/compiler/extendPrivateConstructorClass2.ts @@ -36,14 +36,36 @@ declare const jS: typeof j1 & typeof j2; declare class j0 extends jS {} // error abstract class j3 { - private constructor(arg: number) {} - method(_any: any) { + private constructor(...args: any[]) {} + method1() { abstract class j4 { - private constructor(arg: number) {} + private constructor(...args: any[]) {} + method2(_any: any) { + const jS: typeof j3 & typeof j4 = _any; + + // bizarre but ok + class j0 extends jS { + method1() {} + method2() {} + } + } } + } +} - const jS: typeof j3 & typeof j4 = _any; +abstract class j5 { + private constructor(...args: any[]) {} + method1(_any: any) { + abstract class j6 { + private constructor(...args: any[]) {} + method2() {} + } + const jS: typeof j5 & typeof j6 = _any; - declare class j0 extends jS {} // bizarre but ok + // bizarre but ok too given the base is a result of a mixin + class j0 extends jS { + method1() {} + method2() {} + } } } From 5a18e53939249e429038c7458e5a4f6d5d16b2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 17 Oct 2025 23:58:19 +0200 Subject: [PATCH 5/6] extra tests --- .../extendPrivateConstructorClass2.errors.txt | 85 ++++++- .../extendPrivateConstructorClass2.symbols | 149 ++++++++++++- .../extendPrivateConstructorClass2.types | 209 ++++++++++++++++-- .../extendPrivateConstructorClass2.ts | 71 +++++- 4 files changed, 477 insertions(+), 37 deletions(-) diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt index e630f98a03273..b8da61049b8c6 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt +++ b/tests/baselines/reference/extendPrivateConstructorClass2.errors.txt @@ -3,9 +3,13 @@ extendPrivateConstructorClass2.ts(11,24): error TS2675: Cannot extend a class 'A extendPrivateConstructorClass2.ts(22,1): error TS2673: Constructor of class 'B2' is private and only accessible within the class declaration. extendPrivateConstructorClass2.ts(23,24): error TS2675: Cannot extend a class 'B2'. Class constructor is marked as private. extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j1'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(79,26): error TS2510: Base constructors must all have the same return type. +extendPrivateConstructorClass2.ts(98,22): error TS2510: Base constructors must all have the same return type. +extendPrivateConstructorClass2.ts(98,22): error TS2675: Cannot extend a class 'j10'. Class constructor is marked as private. +extendPrivateConstructorClass2.ts(129,22): error TS2675: Cannot extend a class 'j14'. Class constructor is marked as private. -==== extendPrivateConstructorClass2.ts (5 errors) ==== +==== extendPrivateConstructorClass2.ts (9 errors) ==== class A1 { private constructor(arg: string) {} } @@ -55,8 +59,8 @@ extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j method1() { abstract class j4 { private constructor(...args: any[]) {} - method2(_any: any) { - const jS: typeof j3 & typeof j4 = _any; + method2() { + const jS: typeof j3 & typeof j4 = null!; // bizarre but ok class j0 extends jS { @@ -70,12 +74,12 @@ extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j abstract class j5 { private constructor(...args: any[]) {} - method1(_any: any) { + method1() { abstract class j6 { private constructor(...args: any[]) {} method2() {} } - const jS: typeof j5 & typeof j6 = _any; + const jS: typeof j5 & typeof j6 = null!; // bizarre but ok too given the base is a result of a mixin class j0 extends jS { @@ -84,4 +88,75 @@ extendPrivateConstructorClass2.ts(33,26): error TS2675: Cannot extend a class 'j } } } + + abstract class j7 { + private constructor(arg: string) {} + method1() { + abstract class j8 { + private constructor(arg: number) {} + method2() { + const jS: typeof j7 & typeof j8 = null!; + + // error + class j0 extends jS { + ~~ +!!! error TS2510: Base constructors must all have the same return type. + method1() {} + method2() {} + } + } + } + } + } + + abstract class j9 { + private constructor(arg: string) {} + method1() { + abstract class j10 { + private constructor(arg: number) {} + method2() {} + } + const jS: typeof j9 & typeof j10 = null!; + + // error + class j0 extends jS { + ~~ +!!! error TS2510: Base constructors must all have the same return type. + ~~ +!!! error TS2675: Cannot extend a class 'j10'. Class constructor is marked as private. + method1() {} + method2() {} + } + } + } + + abstract class j11 { + private constructor(arg: string) {} + static { + abstract class j12 { + private constructor(arg: number) {} + static { + const jS: typeof j11 & typeof j12 = null!; + + // ok + class j0 extends jS {} + } + } + } + } + + abstract class j13 { + private constructor(arg: string) {} + static { + abstract class j14 { + private constructor(arg: number) {} + } + const jS: typeof j13 & typeof j14 = null!; + + // error + class j0 extends jS {} + ~~ +!!! error TS2675: Cannot extend a class 'j14'. Class constructor is marked as private. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.symbols b/tests/baselines/reference/extendPrivateConstructorClass2.symbols index e33455fafbb50..08ec1ab380651 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.symbols +++ b/tests/baselines/reference/extendPrivateConstructorClass2.symbols @@ -88,19 +88,17 @@ abstract class j3 { private constructor(...args: any[]) {} >args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 38, 26)) - method2(_any: any) { + method2() { >method2 : Symbol(j4.method2, Decl(extendPrivateConstructorClass2.ts, 38, 44)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 39, 14)) - const jS: typeof j3 & typeof j4 = _any; + const jS: typeof j3 & typeof j4 = null!; >jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 40, 13)) >j3 : Symbol(j3, Decl(extendPrivateConstructorClass2.ts, 32, 30)) >j4 : Symbol(j4, Decl(extendPrivateConstructorClass2.ts, 36, 13)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 39, 14)) // bizarre but ok class j0 extends jS { ->j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 40, 47)) +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 40, 48)) >jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 40, 13)) method1() {} @@ -120,12 +118,11 @@ abstract class j5 { private constructor(...args: any[]) {} >args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 53, 22)) - method1(_any: any) { + method1() { >method1 : Symbol(j5.method1, Decl(extendPrivateConstructorClass2.ts, 53, 40)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 54, 10)) abstract class j6 { ->j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 22)) +>j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 13)) private constructor(...args: any[]) {} >args : Symbol(args, Decl(extendPrivateConstructorClass2.ts, 56, 26)) @@ -133,15 +130,14 @@ abstract class j5 { method2() {} >method2 : Symbol(j6.method2, Decl(extendPrivateConstructorClass2.ts, 56, 44)) } - const jS: typeof j5 & typeof j6 = _any; + const jS: typeof j5 & typeof j6 = null!; >jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 59, 9)) >j5 : Symbol(j5, Decl(extendPrivateConstructorClass2.ts, 50, 1)) ->j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 22)) ->_any : Symbol(_any, Decl(extendPrivateConstructorClass2.ts, 54, 10)) +>j6 : Symbol(j6, Decl(extendPrivateConstructorClass2.ts, 54, 13)) // bizarre but ok too given the base is a result of a mixin class j0 extends jS { ->j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 59, 43)) +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 59, 44)) >jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 59, 9)) method1() {} @@ -153,3 +149,132 @@ abstract class j5 { } } +abstract class j7 { +>j7 : Symbol(j7, Decl(extendPrivateConstructorClass2.ts, 67, 1)) + + private constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 70, 22)) + + method1() { +>method1 : Symbol(j7.method1, Decl(extendPrivateConstructorClass2.ts, 70, 37)) + + abstract class j8 { +>j8 : Symbol(j8, Decl(extendPrivateConstructorClass2.ts, 71, 13)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 73, 26)) + + method2() { +>method2 : Symbol(j8.method2, Decl(extendPrivateConstructorClass2.ts, 73, 41)) + + const jS: typeof j7 & typeof j8 = null!; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 75, 13)) +>j7 : Symbol(j7, Decl(extendPrivateConstructorClass2.ts, 67, 1)) +>j8 : Symbol(j8, Decl(extendPrivateConstructorClass2.ts, 71, 13)) + + // error + class j0 extends jS { +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 75, 48)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 75, 13)) + + method1() {} +>method1 : Symbol(j0.method1, Decl(extendPrivateConstructorClass2.ts, 78, 29)) + + method2() {} +>method2 : Symbol(j0.method2, Decl(extendPrivateConstructorClass2.ts, 79, 22)) + } + } + } + } +} + +abstract class j9 { +>j9 : Symbol(j9, Decl(extendPrivateConstructorClass2.ts, 85, 1)) + + private constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 88, 22)) + + method1() { +>method1 : Symbol(j9.method1, Decl(extendPrivateConstructorClass2.ts, 88, 37)) + + abstract class j10 { +>j10 : Symbol(j10, Decl(extendPrivateConstructorClass2.ts, 89, 13)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 91, 26)) + + method2() {} +>method2 : Symbol(j10.method2, Decl(extendPrivateConstructorClass2.ts, 91, 41)) + } + const jS: typeof j9 & typeof j10 = null!; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 94, 9)) +>j9 : Symbol(j9, Decl(extendPrivateConstructorClass2.ts, 85, 1)) +>j10 : Symbol(j10, Decl(extendPrivateConstructorClass2.ts, 89, 13)) + + // error + class j0 extends jS { +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 94, 45)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 94, 9)) + + method1() {} +>method1 : Symbol(j0.method1, Decl(extendPrivateConstructorClass2.ts, 97, 25)) + + method2() {} +>method2 : Symbol(j0.method2, Decl(extendPrivateConstructorClass2.ts, 98, 18)) + } + } +} + +abstract class j11 { +>j11 : Symbol(j11, Decl(extendPrivateConstructorClass2.ts, 102, 1)) + + private constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 105, 22)) + + static { + abstract class j12 { +>j12 : Symbol(j12, Decl(extendPrivateConstructorClass2.ts, 106, 10)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 108, 26)) + + static { + const jS: typeof j11 & typeof j12 = null!; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 110, 13)) +>j11 : Symbol(j11, Decl(extendPrivateConstructorClass2.ts, 102, 1)) +>j12 : Symbol(j12, Decl(extendPrivateConstructorClass2.ts, 106, 10)) + + // ok + class j0 extends jS {} +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 110, 50)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 110, 13)) + } + } + } +} + +abstract class j13 { +>j13 : Symbol(j13, Decl(extendPrivateConstructorClass2.ts, 117, 1)) + + private constructor(arg: string) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 120, 22)) + + static { + abstract class j14 { +>j14 : Symbol(j14, Decl(extendPrivateConstructorClass2.ts, 121, 10)) + + private constructor(arg: number) {} +>arg : Symbol(arg, Decl(extendPrivateConstructorClass2.ts, 123, 26)) + } + const jS: typeof j13 & typeof j14 = null!; +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 125, 9)) +>j13 : Symbol(j13, Decl(extendPrivateConstructorClass2.ts, 117, 1)) +>j14 : Symbol(j14, Decl(extendPrivateConstructorClass2.ts, 121, 10)) + + // error + class j0 extends jS {} +>j0 : Symbol(j0, Decl(extendPrivateConstructorClass2.ts, 125, 46)) +>jS : Symbol(jS, Decl(extendPrivateConstructorClass2.ts, 125, 9)) + } +} + diff --git a/tests/baselines/reference/extendPrivateConstructorClass2.types b/tests/baselines/reference/extendPrivateConstructorClass2.types index 288803e0b0f75..96c1d3a6654ef 100644 --- a/tests/baselines/reference/extendPrivateConstructorClass2.types +++ b/tests/baselines/reference/extendPrivateConstructorClass2.types @@ -130,21 +130,19 @@ abstract class j3 { >args : any[] > : ^^^^^ - method2(_any: any) { ->method2 : (_any: any) => void -> : ^ ^^ ^^^^^^^^^ ->_any : any -> : ^^^ + method2() { +>method2 : () => void +> : ^^^^^^^^^^ - const jS: typeof j3 & typeof j4 = _any; + const jS: typeof j3 & typeof j4 = null!; >jS : typeof j3 & typeof j4 > : ^^^^^^^^^^^^^^^^^^^^^ >j3 : typeof j3 > : ^^^^^^^^^ >j4 : typeof j4 > : ^^^^^^^^^ ->_any : any -> : ^^^ +>null! : never +> : ^^^^^ // bizarre but ok class j0 extends jS { @@ -174,11 +172,9 @@ abstract class j5 { >args : any[] > : ^^^^^ - method1(_any: any) { ->method1 : (_any: any) => void -> : ^ ^^ ^^^^^^^^^ ->_any : any -> : ^^^ + method1() { +>method1 : () => void +> : ^^^^^^^^^^ abstract class j6 { >j6 : j6 @@ -192,15 +188,15 @@ abstract class j5 { >method2 : () => void > : ^^^^^^^^^^ } - const jS: typeof j5 & typeof j6 = _any; + const jS: typeof j5 & typeof j6 = null!; >jS : typeof j5 & typeof j6 > : ^^^^^^^^^^^^^^^^^^^^^ >j5 : typeof j5 > : ^^^^^^^^^ >j6 : typeof j6 > : ^^^^^^^^^ ->_any : any -> : ^^^ +>null! : never +> : ^^^^^ // bizarre but ok too given the base is a result of a mixin class j0 extends jS { @@ -220,3 +216,184 @@ abstract class j5 { } } +abstract class j7 { +>j7 : j7 +> : ^^ + + private constructor(arg: string) {} +>arg : string +> : ^^^^^^ + + method1() { +>method1 : () => void +> : ^^^^^^^^^^ + + abstract class j8 { +>j8 : j8 +> : ^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + + method2() { +>method2 : () => void +> : ^^^^^^^^^^ + + const jS: typeof j7 & typeof j8 = null!; +>jS : typeof j7 & typeof j8 +> : ^^^^^^^^^^^^^^^^^^^^^ +>j7 : typeof j7 +> : ^^^^^^^^^ +>j8 : typeof j8 +> : ^^^^^^^^^ +>null! : never +> : ^^^^^ + + // error + class j0 extends jS { +>j0 : j0 +> : ^^ +>jS : j7 +> : ^^ + + method1() {} +>method1 : () => void +> : ^^^^^^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } + } + } + } +} + +abstract class j9 { +>j9 : j9 +> : ^^ + + private constructor(arg: string) {} +>arg : string +> : ^^^^^^ + + method1() { +>method1 : () => void +> : ^^^^^^^^^^ + + abstract class j10 { +>j10 : j10 +> : ^^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } + const jS: typeof j9 & typeof j10 = null!; +>jS : typeof j9 & typeof j10 +> : ^^^^^^^^^^^^^^^^^^^^^^ +>j9 : typeof j9 +> : ^^^^^^^^^ +>j10 : typeof j10 +> : ^^^^^^^^^^ +>null! : never +> : ^^^^^ + + // error + class j0 extends jS { +>j0 : j0 +> : ^^ +>jS : j9 +> : ^^ + + method1() {} +>method1 : () => void +> : ^^^^^^^^^^ + + method2() {} +>method2 : () => void +> : ^^^^^^^^^^ + } + } +} + +abstract class j11 { +>j11 : j11 +> : ^^^ + + private constructor(arg: string) {} +>arg : string +> : ^^^^^^ + + static { + abstract class j12 { +>j12 : j12 +> : ^^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + + static { + const jS: typeof j11 & typeof j12 = null!; +>jS : typeof j11 & typeof j12 +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>j11 : typeof j11 +> : ^^^^^^^^^^ +>j12 : typeof j12 +> : ^^^^^^^^^^ +>null! : never +> : ^^^^^ + + // ok + class j0 extends jS {} +>j0 : j0 +> : ^^ +>jS : j11 +> : ^^^ + } + } + } +} + +abstract class j13 { +>j13 : j13 +> : ^^^ + + private constructor(arg: string) {} +>arg : string +> : ^^^^^^ + + static { + abstract class j14 { +>j14 : j14 +> : ^^^ + + private constructor(arg: number) {} +>arg : number +> : ^^^^^^ + } + const jS: typeof j13 & typeof j14 = null!; +>jS : typeof j13 & typeof j14 +> : ^^^^^^^^^^^^^^^^^^^^^^^ +>j13 : typeof j13 +> : ^^^^^^^^^^ +>j14 : typeof j14 +> : ^^^^^^^^^^ +>null! : never +> : ^^^^^ + + // error + class j0 extends jS {} +>j0 : j0 +> : ^^ +>jS : j13 +> : ^^^ + } +} + diff --git a/tests/cases/compiler/extendPrivateConstructorClass2.ts b/tests/cases/compiler/extendPrivateConstructorClass2.ts index 9e060cbdb29f3..22b81c58ca466 100644 --- a/tests/cases/compiler/extendPrivateConstructorClass2.ts +++ b/tests/cases/compiler/extendPrivateConstructorClass2.ts @@ -40,8 +40,8 @@ abstract class j3 { method1() { abstract class j4 { private constructor(...args: any[]) {} - method2(_any: any) { - const jS: typeof j3 & typeof j4 = _any; + method2() { + const jS: typeof j3 & typeof j4 = null!; // bizarre but ok class j0 extends jS { @@ -55,12 +55,12 @@ abstract class j3 { abstract class j5 { private constructor(...args: any[]) {} - method1(_any: any) { + method1() { abstract class j6 { private constructor(...args: any[]) {} method2() {} } - const jS: typeof j5 & typeof j6 = _any; + const jS: typeof j5 & typeof j6 = null!; // bizarre but ok too given the base is a result of a mixin class j0 extends jS { @@ -69,3 +69,66 @@ abstract class j5 { } } } + +abstract class j7 { + private constructor(arg: string) {} + method1() { + abstract class j8 { + private constructor(arg: number) {} + method2() { + const jS: typeof j7 & typeof j8 = null!; + + // error + class j0 extends jS { + method1() {} + method2() {} + } + } + } + } +} + +abstract class j9 { + private constructor(arg: string) {} + method1() { + abstract class j10 { + private constructor(arg: number) {} + method2() {} + } + const jS: typeof j9 & typeof j10 = null!; + + // error + class j0 extends jS { + method1() {} + method2() {} + } + } +} + +abstract class j11 { + private constructor(arg: string) {} + static { + abstract class j12 { + private constructor(arg: number) {} + static { + const jS: typeof j11 & typeof j12 = null!; + + // ok + class j0 extends jS {} + } + } + } +} + +abstract class j13 { + private constructor(arg: string) {} + static { + abstract class j14 { + private constructor(arg: number) {} + } + const jS: typeof j13 & typeof j14 = null!; + + // error + class j0 extends jS {} + } +} From 42cdf5955726278a5a672c5ad43763d3f53dd8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 18 Oct 2025 09:16:52 +0200 Subject: [PATCH 6/6] fmt --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index af7df91221824..e77aa179c7f7b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37171,7 +37171,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return { kind: modifiers, declaringClass: getDeclaredTypeOfSymbol(declaration.parent.symbol), - } + }; } } return undefined;