From a7028cd03a472a7f1cf57091fcf9fc9bf2483264 Mon Sep 17 00:00:00 2001 From: hesam-oxe Date: Thu, 11 Jun 2026 20:14:18 +0330 Subject: [PATCH 1/2] fix: report error for private property access on generic intersection types Added check in getIndexedAccessTypeOrUndefined to detect conflicting private properties in intersection types before resolving indexed access. Closes #62294 --- src/compiler/checker.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..a09d2a51914fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19656,6 +19656,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return wildcardType; } objectType = getReducedType(objectType); + // If the object type is an intersection with conflicting private properties, + // report an error — we shouldn't be able to access those properties via T["key"] + if (objectType.flags & TypeFlags.Intersection && !(objectType.flags & TypeFlags.Never)) { + const props = getPropertiesOfUnionOrIntersectionType(objectType as IntersectionType); + const conflictingPrivate = find(props, isConflictingPrivateProperty); + if (conflictingPrivate && accessNode) { + error(accessNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, + symbolToString(conflictingPrivate), typeToString(getDeclaringClass(conflictingPrivate)!)); + return undefined; + } + } // If the object type has a string index signature and no other members we know that the result will // always be the type of that index signature and we can simplify accordingly. if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { From 4013aae8560738d62d49e3362e4b141b624766e8 Mon Sep 17 00:00:00 2001 From: hesam-oxe Date: Thu, 11 Jun 2026 20:20:07 +0330 Subject: [PATCH 2/2] fix: handle missing accessNode and null declaringClass --- src/compiler/checker.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a09d2a51914fb..c3b3d129b0d28 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19661,9 +19661,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (objectType.flags & TypeFlags.Intersection && !(objectType.flags & TypeFlags.Never)) { const props = getPropertiesOfUnionOrIntersectionType(objectType as IntersectionType); const conflictingPrivate = find(props, isConflictingPrivateProperty); - if (conflictingPrivate && accessNode) { - error(accessNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, - symbolToString(conflictingPrivate), typeToString(getDeclaringClass(conflictingPrivate)!)); + if (conflictingPrivate) { + if (accessNode) { + const declaringClass = getDeclaringClass(conflictingPrivate); + if (declaringClass) { + error(accessNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, + symbolToString(conflictingPrivate), typeToString(declaringClass)); + } + } return undefined; } }