From 3bb8f5893656c07678ad11aefc6cafe31ff03728 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 20 Aug 2026 13:19:56 -0700 Subject: [PATCH 01/10] Fix getDeclarationModifierFlagsFromSymbolEx for synthetic properties --- tsc/internal/checker/utilities.go | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 69b2362c8fb58..eefb49c81420e 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -715,6 +715,22 @@ func getDeclarationModifierFlagsFromSymbol(s *ast.Symbol) ast.ModifierFlags { } func getDeclarationModifierFlagsFromSymbolEx(s *ast.Symbol, isWrite bool) ast.ModifierFlags { + if s.CheckFlags&ast.CheckFlagsSynthetic != 0 { + var accessModifier ast.ModifierFlags + switch { + case s.CheckFlags&ast.CheckFlagsContainsPrivate != 0: + accessModifier = ast.ModifierFlagsPrivate + case s.CheckFlags&ast.CheckFlagsContainsPublic != 0: + accessModifier = ast.ModifierFlagsPublic + default: + accessModifier = ast.ModifierFlagsProtected + } + var staticModifier ast.ModifierFlags + if s.CheckFlags&ast.CheckFlagsContainsStatic != 0 { + staticModifier = ast.ModifierFlagsStatic + } + return accessModifier | staticModifier + } if s.ValueDeclaration != nil { var declaration *ast.Node if isWrite { @@ -732,22 +748,6 @@ func getDeclarationModifierFlagsFromSymbolEx(s *ast.Symbol, isWrite bool) ast.Mo } return flags & ^ast.ModifierFlagsAccessibilityModifier } - if s.CheckFlags&ast.CheckFlagsSynthetic != 0 { - var accessModifier ast.ModifierFlags - switch { - case s.CheckFlags&ast.CheckFlagsContainsPrivate != 0: - accessModifier = ast.ModifierFlagsPrivate - case s.CheckFlags&ast.CheckFlagsContainsPublic != 0: - accessModifier = ast.ModifierFlagsPublic - default: - accessModifier = ast.ModifierFlagsProtected - } - var staticModifier ast.ModifierFlags - if s.CheckFlags&ast.CheckFlagsContainsStatic != 0 { - staticModifier = ast.ModifierFlagsStatic - } - return accessModifier | staticModifier - } if s.Flags&ast.SymbolFlagsPrototype != 0 { return ast.ModifierFlagsPublic | ast.ModifierFlagsStatic } From 3d75121c1d8969273cc0cab5c663a923caa8a637 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 20 Aug 2026 13:20:05 -0700 Subject: [PATCH 02/10] Add regression test --- .../syntheticProtectedProperties.symbols | 73 +++++++++++++++++++ .../syntheticProtectedProperties.types | 67 +++++++++++++++++ .../compiler/syntheticProtectedProperties.ts | 30 ++++++++ 3 files changed, 170 insertions(+) create mode 100644 tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types create mode 100644 tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols new file mode 100644 index 0000000000000..4e967c48bc616 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols @@ -0,0 +1,73 @@ +//// [tests/cases/compiler/syntheticProtectedProperties.ts] //// + +=== syntheticProtectedProperties.ts === +// https://github.com/microsoft/TypeScript/issues/63749 + +declare class Dummy { +>Dummy : Symbol(Dummy, Decl(syntheticProtectedProperties.ts, 0, 0)) + + a: number; +>a : Symbol(Dummy.a, Decl(syntheticProtectedProperties.ts, 2, 21)) +} + +type Public = Base | Dummy; +>Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) +>Base : Symbol(Base, Decl(syntheticProtectedProperties.ts, 6, 27)) +>Dummy : Symbol(Dummy, Decl(syntheticProtectedProperties.ts, 0, 0)) + +declare class Base { +>Base : Symbol(Base, Decl(syntheticProtectedProperties.ts, 6, 27)) + + protected get content(): string; +>content : Symbol(Base.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36)) + + protected set content(value: string); +>content : Symbol(Base.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 10, 26)) +} + +declare class Mock { +>Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) + + get content(): string; +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) + + set content(value: string); +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 15, 16)) +} + +declare const w: Public +>w : Symbol(w, Decl(syntheticProtectedProperties.ts, 18, 13)) +>Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) + +if (w instanceof Mock) { +>w : Symbol(w, Decl(syntheticProtectedProperties.ts, 18, 13)) +>Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) + + w.content; +>w.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w : Symbol(w, Decl(syntheticProtectedProperties.ts, 18, 13)) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +} +declare const w2: Mock & Public +>w2 : Symbol(w2, Decl(syntheticProtectedProperties.ts, 22, 13)) +>Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) +>Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) + +w2.content; +>w2.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w2 : Symbol(w2, Decl(syntheticProtectedProperties.ts, 22, 13)) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) + + +declare const w3: Public & Mock +>w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 26, 13)) +>Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) +>Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) + +w3.content; +>w3.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 26, 13)) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) + diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types new file mode 100644 index 0000000000000..a5c97d43734dc --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/syntheticProtectedProperties.ts] //// + +=== syntheticProtectedProperties.ts === +// https://github.com/microsoft/TypeScript/issues/63749 + +declare class Dummy { +>Dummy : Dummy + + a: number; +>a : number +} + +type Public = Base | Dummy; +>Public : Public + +declare class Base { +>Base : Base + + protected get content(): string; +>content : string + + protected set content(value: string); +>content : string +>value : string +} + +declare class Mock { +>Mock : Mock + + get content(): string; +>content : string + + set content(value: string); +>content : string +>value : string +} + +declare const w: Public +>w : Public + +if (w instanceof Mock) { +>w instanceof Mock : boolean +>w : Public +>Mock : typeof Mock + + w.content; +>w.content : string +>w : Public & Mock +>content : string +} +declare const w2: Mock & Public +>w2 : Mock & Public + +w2.content; +>w2.content : string +>w2 : Mock & Public +>content : string + + +declare const w3: Public & Mock +>w3 : Public & Mock + +w3.content; +>w3.content : string +>w3 : Public & Mock +>content : string + diff --git a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts new file mode 100644 index 0000000000000..ad088da1dff68 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts @@ -0,0 +1,30 @@ +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/63749 + +declare class Dummy { + a: number; +} + +type Public = Base | Dummy; + +declare class Base { + protected get content(): string; + protected set content(value: string); +} + +declare class Mock { + get content(): string; + set content(value: string); +} + +declare const w: Public +if (w instanceof Mock) { + w.content; +} +declare const w2: Mock & Public +w2.content; + + +declare const w3: Public & Mock +w3.content; From ed035d4653ad34cc03636f79faeaf4e2630e83ec Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 21 Aug 2026 17:24:40 -0700 Subject: [PATCH 03/10] Properly track set accessor modifiers in unions/intersections --- tsc/internal/ast/checkflags.go | 29 ++++++++++++++++------------- tsc/internal/checker/checker.go | 18 ++++++++++++------ tsc/internal/checker/utilities.go | 13 ++++++------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/tsc/internal/ast/checkflags.go b/tsc/internal/ast/checkflags.go index b928d3878508e..7800a585d6355 100644 --- a/tsc/internal/ast/checkflags.go +++ b/tsc/internal/ast/checkflags.go @@ -17,19 +17,22 @@ const ( CheckFlagsContainsPublic CheckFlags = 1 << 8 // Synthetic property with public constituent(s) CheckFlagsContainsProtected CheckFlags = 1 << 9 // Synthetic property with protected constituent(s) CheckFlagsContainsPrivate CheckFlags = 1 << 10 // Synthetic property with private constituent(s) - CheckFlagsContainsStatic CheckFlags = 1 << 11 // Synthetic property with static constituent(s) - CheckFlagsLate CheckFlags = 1 << 12 // Late-bound symbol for a computed property with a dynamic name - CheckFlagsReverseMapped CheckFlags = 1 << 13 // Property of reverse-inferred homomorphic mapped type - CheckFlagsOptionalParameter CheckFlags = 1 << 14 // Optional parameter - CheckFlagsRestParameter CheckFlags = 1 << 15 // Rest parameter - CheckFlagsDeferredType CheckFlags = 1 << 16 // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType` - CheckFlagsHasNeverType CheckFlags = 1 << 17 // Synthetic property with at least one never type in constituents - CheckFlagsMapped CheckFlags = 1 << 18 // Property of mapped type - CheckFlagsStripOptional CheckFlags = 1 << 19 // Strip optionality in mapped property - CheckFlagsUnresolved CheckFlags = 1 << 20 // Unresolved type alias symbol - CheckFlagsIsDiscriminantComputed CheckFlags = 1 << 21 // IsDiscriminant flags has been computed - CheckFlagsIsDiscriminant CheckFlags = 1 << 22 // Discriminant property - CheckFlagsIndexSymbol CheckFlags = 1 << 23 // Synthetic property created from index signature + CheckFlagsContainsWritePublic CheckFlags = 1 << 11 // Synthetic property with public set accessors(s) + CheckFlagsContainsWriteProtected CheckFlags = 1 << 12 // Synthetic property with protected set accessors(s) + CheckFlagsContainsWritePrivate CheckFlags = 1 << 13 // Synthetic property with private set accessors(s) + CheckFlagsContainsStatic CheckFlags = 1 << 14 // Synthetic property with static constituent(s) + CheckFlagsLate CheckFlags = 1 << 15 // Late-bound symbol for a computed property with a dynamic name + CheckFlagsReverseMapped CheckFlags = 1 << 16 // Property of reverse-inferred homomorphic mapped type + CheckFlagsOptionalParameter CheckFlags = 1 << 17 // Optional parameter + CheckFlagsRestParameter CheckFlags = 1 << 18 // Rest parameter + CheckFlagsDeferredType CheckFlags = 1 << 19 // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType` + CheckFlagsHasNeverType CheckFlags = 1 << 20 // Synthetic property with at least one never type in constituents + CheckFlagsMapped CheckFlags = 1 << 21 // Property of mapped type + CheckFlagsStripOptional CheckFlags = 1 << 22 // Strip optionality in mapped property + CheckFlagsUnresolved CheckFlags = 1 << 23 // Unresolved type alias symbol + CheckFlagsIsDiscriminantComputed CheckFlags = 1 << 24 // IsDiscriminant flags has been computed + CheckFlagsIsDiscriminant CheckFlags = 1 << 25 // Discriminant property + CheckFlagsIndexSymbol CheckFlags = 1 << 26 // Synthetic property created from index signature CheckFlagsSynthetic = CheckFlagsSyntheticProperty | CheckFlagsSyntheticMethod CheckFlagsNonUniformAndLiteral = CheckFlagsHasNonUniformType | CheckFlagsHasLiteralType CheckFlagsPartial = CheckFlagsReadPartial | CheckFlagsWritePartial diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 2a4ead5003a89..f25d270565e1f 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -21585,6 +21585,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s var modifiers ast.ModifierFlags if prop != nil { modifiers = getDeclarationModifierFlagsFromSymbol(prop) + writeModifiers := getDeclarationModifierFlagsFromSymbolEx(prop, true /*isWrite*/) if prop.Flags&ast.SymbolFlagsClassMember != 0 { if isUnion { optionalFlag |= prop.Flags & ast.SymbolFlagsOptional @@ -21624,14 +21625,19 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s } else if !isUnion && !c.isReadonlySymbol(prop) { checkFlags &^= ast.CheckFlagsReadonly } - if modifiers&ast.ModifierFlagsNonPublicAccessibilityModifier == 0 { - checkFlags |= ast.CheckFlagsContainsPublic - } - if modifiers&ast.ModifierFlagsProtected != 0 { + if modifiers&ast.ModifierFlagsProtected != 0 && modifiers&ast.ModifierFlagsPublic == 0 { checkFlags |= ast.CheckFlagsContainsProtected - } - if modifiers&ast.ModifierFlagsPrivate != 0 { + } else if modifiers&ast.ModifierFlagsPrivate != 0 && modifiers&ast.ModifierFlagsPublic == 0 { checkFlags |= ast.CheckFlagsContainsPrivate + } else { + checkFlags |= ast.CheckFlagsContainsPublic + } + if writeModifiers&ast.ModifierFlagsProtected != 0 && writeModifiers&ast.ModifierFlagsPublic == 0 { + checkFlags |= ast.CheckFlagsContainsWriteProtected + } else if writeModifiers&ast.ModifierFlagsPrivate != 0 && writeModifiers&ast.ModifierFlagsPublic == 0 { + checkFlags |= ast.CheckFlagsContainsWritePrivate + } else { + checkFlags |= ast.CheckFlagsContainsWritePublic } if modifiers&ast.ModifierFlagsStatic != 0 { checkFlags |= ast.CheckFlagsContainsStatic diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index eefb49c81420e..9c486a5bb90ab 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -718,18 +718,17 @@ func getDeclarationModifierFlagsFromSymbolEx(s *ast.Symbol, isWrite bool) ast.Mo if s.CheckFlags&ast.CheckFlagsSynthetic != 0 { var accessModifier ast.ModifierFlags switch { - case s.CheckFlags&ast.CheckFlagsContainsPrivate != 0: - accessModifier = ast.ModifierFlagsPrivate - case s.CheckFlags&ast.CheckFlagsContainsPublic != 0: + case !isWrite && s.CheckFlags&ast.CheckFlagsContainsPublic != 0 || isWrite && s.CheckFlags&ast.CheckFlagsContainsWritePublic != 0: accessModifier = ast.ModifierFlagsPublic - default: + case !isWrite && s.CheckFlags&ast.CheckFlagsContainsProtected != 0 || isWrite && s.CheckFlags&ast.CheckFlagsContainsWriteProtected != 0: accessModifier = ast.ModifierFlagsProtected + case !isWrite && s.CheckFlags&ast.CheckFlagsContainsPrivate != 0 || isWrite && s.CheckFlags&ast.CheckFlagsContainsWritePrivate != 0: + accessModifier = ast.ModifierFlagsPrivate } - var staticModifier ast.ModifierFlags if s.CheckFlags&ast.CheckFlagsContainsStatic != 0 { - staticModifier = ast.ModifierFlagsStatic + return accessModifier | ast.ModifierFlagsStatic } - return accessModifier | staticModifier + return accessModifier } if s.ValueDeclaration != nil { var declaration *ast.Node From d9d74974b458e9b4c9b19133a83b299f8c530f03 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 22 Aug 2026 13:44:56 -0700 Subject: [PATCH 04/10] Handle differing read/write accessibility in union properties --- tsc/internal/checker/checker.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index f25d270565e1f..88ef07d76a724 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -21671,13 +21671,27 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s } } } - if singleProp == nil || isUnion && + if singleProp == nil { + // No property was found + return nil + } + if isUnion && (propSet.Size() != 0 || checkFlags&ast.CheckFlagsPartial != 0) && - checkFlags&(ast.CheckFlagsContainsPrivate|ast.CheckFlagsContainsProtected) != 0 && + checkFlags&(ast.CheckFlagsContainsPrivate|ast.CheckFlagsContainsProtected|ast.CheckFlagsContainsWritePrivate|ast.CheckFlagsContainsWriteProtected) != 0 && !(propSet.Size() != 0 && c.hasCommonDeclaration(&propSet)) { - // No property was found, or, in a union, a property has a private or protected declaration in one - // constituent, but is missing or has a different declaration in another constituent. - return nil + // A property in a union has a private or protected declaration in one constituent, but is missing + // or has a different declaration in another constituent. If the private or protected declaration is + // for reading, we don't create a property. + if checkFlags&(ast.CheckFlagsContainsPrivate|ast.CheckFlagsContainsProtected) != 0 { + return nil + } + // If the private or protected declaration is for writing, we give the write-side of the property + // the most restrictive accessbility of the constituents. + if checkFlags&ast.CheckFlagsContainsWritePrivate != 0 { + checkFlags &^= ast.CheckFlagsContainsWritePublic | ast.CheckFlagsContainsWriteProtected + } else if checkFlags&ast.CheckFlagsContainsWriteProtected != 0 { + checkFlags &^= ast.CheckFlagsContainsWritePublic + } } if propSet.Size() == 0 && checkFlags&ast.CheckFlagsReadPartial == 0 && len(indexTypes) == 0 { if !mergedInstantiations { From 07ef369693efb3a444b0c53f2afce84face3cd54 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 22 Aug 2026 13:45:05 -0700 Subject: [PATCH 05/10] Add tests --- .../syntheticProtectedProperties.errors.txt | 94 +++++++++++++ .../syntheticProtectedProperties.symbols | 126 ++++++++++++++++- .../syntheticProtectedProperties.types | 130 +++++++++++++++++- .../compiler/syntheticProtectedProperties.ts | 46 ++++++- 4 files changed, 391 insertions(+), 5 deletions(-) create mode 100644 tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt new file mode 100644 index 0000000000000..541729563e4d0 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt @@ -0,0 +1,94 @@ +syntheticProtectedProperties.ts(50,6): error TS2445: Property 'foo' is protected and only accessible within class 'C1 | C2' and its subclasses. +syntheticProtectedProperties.ts(53,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(54,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(57,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(58,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(72,6): error TS2445: Property 'foo' is protected and only accessible within class 'C2 & C3' and its subclasses. + + +==== syntheticProtectedProperties.ts (6 errors) ==== + // https://github.com/microsoft/TypeScript/issues/63749 + + declare class Dummy { + a: number; + } + + type Public = Base | Dummy; + + declare class Base { + protected get content(): string; + protected set content(value: string); + } + + declare class Mock { + get content(): string; + set content(value: string); + } + + declare const w: Public + if (w instanceof Mock) { + w.content; + } + declare const w2: Mock & Public + w2.content; + + declare const w3: Public & Mock + w3.content; + + // private/protected set accessors are tracked in unions and intersections + + declare class C1 { + get foo(): number; + set foo(value: number); + } + + declare class C2 { + get foo(): number; + protected set foo(value: number); + } + + declare class C3 { + protected get foo(): number; + protected set foo(value: number); + } + + // Unions properties have most restricted accessibility + + declare const cu12: C1 | C2; + cu12.foo; + cu12.foo = 123; // Error + ~~~ +!!! error TS2445: Property 'foo' is protected and only accessible within class 'C1 | C2' and its subclasses. + + declare const cu13: C1 | C3; + cu13.foo; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + cu13.foo = 123; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + + declare const cu22: C2 | C3; + cu13.foo; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + cu13.foo = 123; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + + // Intersection properties have most permissive accessibility + + declare const ci12: C1 & C2; + ci12.foo; + ci12.foo = 123; + + declare const ci13: C1 & C3; + ci12.foo; + ci12.foo = 123; + + declare const ci23: C2 & C3; + ci23.foo; + ci23.foo = 123; // Error + ~~~ +!!! error TS2445: Property 'foo' is protected and only accessible within class 'C2 & C3' and its subclasses. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols index 4e967c48bc616..bc08d9aa06dec 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols @@ -60,14 +60,134 @@ w2.content; >w2 : Symbol(w2, Decl(syntheticProtectedProperties.ts, 22, 13)) >content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) - declare const w3: Public & Mock ->w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 26, 13)) +>w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 25, 13)) >Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) >Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) w3.content; >w3.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) ->w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 26, 13)) +>w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 25, 13)) >content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +// private/protected set accessors are tracked in unions and intersections + +declare class C1 { +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) + + get foo(): number; +>foo : Symbol(C1.foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22)) + + set foo(value: number); +>foo : Symbol(C1.foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 32, 12)) +} + +declare class C2 { +>C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) + + get foo(): number; +>foo : Symbol(C2.foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + + protected set foo(value: number); +>foo : Symbol(C2.foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 37, 22)) +} + +declare class C3 { +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + + protected get foo(): number; +>foo : Symbol(C3.foo, Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) + + protected set foo(value: number); +>foo : Symbol(C3.foo, Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 42, 22)) +} + +// Unions properties have most restricted accessibility + +declare const cu12: C1 | C2; +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) + +cu12.foo; +>cu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +cu12.foo = 123; // Error +>cu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +declare const cu13: C1 | C3; +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +cu13.foo; // Error +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) + +cu13.foo = 123; // Error +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) + +declare const cu22: C2 | C3; +>cu22 : Symbol(cu22, Decl(syntheticProtectedProperties.ts, 55, 13)) +>C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +cu13.foo; // Error +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) + +cu13.foo = 123; // Error +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) + +// Intersection properties have most permissive accessibility + +declare const ci12: C1 & C2; +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) + +ci12.foo; +>ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +ci12.foo = 123; +>ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +declare const ci13: C1 & C3; +>ci13 : Symbol(ci13, Decl(syntheticProtectedProperties.ts, 65, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +ci12.foo; +>ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +ci12.foo = 123; +>ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) + +declare const ci23: C2 & C3; +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +ci23.foo; +>ci23.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) + +ci23.foo = 123; // Error +>ci23.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) + diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types index a5c97d43734dc..efc6630d9757f 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types @@ -56,7 +56,6 @@ w2.content; >w2 : Mock & Public >content : string - declare const w3: Public & Mock >w3 : Public & Mock @@ -65,3 +64,132 @@ w3.content; >w3 : Public & Mock >content : string +// private/protected set accessors are tracked in unions and intersections + +declare class C1 { +>C1 : C1 + + get foo(): number; +>foo : number + + set foo(value: number); +>foo : number +>value : number +} + +declare class C2 { +>C2 : C2 + + get foo(): number; +>foo : number + + protected set foo(value: number); +>foo : number +>value : number +} + +declare class C3 { +>C3 : C3 + + protected get foo(): number; +>foo : number + + protected set foo(value: number); +>foo : number +>value : number +} + +// Unions properties have most restricted accessibility + +declare const cu12: C1 | C2; +>cu12 : C1 | C2 + +cu12.foo; +>cu12.foo : number +>cu12 : C1 | C2 +>foo : number + +cu12.foo = 123; // Error +>cu12.foo = 123 : 123 +>cu12.foo : number +>cu12 : C1 | C2 +>foo : number +>123 : 123 + +declare const cu13: C1 | C3; +>cu13 : C1 | C3 + +cu13.foo; // Error +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any + +cu13.foo = 123; // Error +>cu13.foo = 123 : 123 +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any +>123 : 123 + +declare const cu22: C2 | C3; +>cu22 : C2 | C3 + +cu13.foo; // Error +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any + +cu13.foo = 123; // Error +>cu13.foo = 123 : 123 +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any +>123 : 123 + +// Intersection properties have most permissive accessibility + +declare const ci12: C1 & C2; +>ci12 : C1 & C2 + +ci12.foo; +>ci12.foo : number +>ci12 : C1 & C2 +>foo : number + +ci12.foo = 123; +>ci12.foo = 123 : 123 +>ci12.foo : number +>ci12 : C1 & C2 +>foo : number +>123 : 123 + +declare const ci13: C1 & C3; +>ci13 : C1 & C3 + +ci12.foo; +>ci12.foo : number +>ci12 : C1 & C2 +>foo : number + +ci12.foo = 123; +>ci12.foo = 123 : 123 +>ci12.foo : number +>ci12 : C1 & C2 +>foo : number +>123 : 123 + +declare const ci23: C2 & C3; +>ci23 : C2 & C3 + +ci23.foo; +>ci23.foo : number +>ci23 : C2 & C3 +>foo : number + +ci23.foo = 123; // Error +>ci23.foo = 123 : 123 +>ci23.foo : number +>ci23 : C2 & C3 +>foo : number +>123 : 123 + diff --git a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts index ad088da1dff68..7975e4f99e9ff 100644 --- a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts +++ b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts @@ -25,6 +25,50 @@ if (w instanceof Mock) { declare const w2: Mock & Public w2.content; - declare const w3: Public & Mock w3.content; + +// private/protected set accessors are tracked in unions and intersections + +declare class C1 { + get foo(): number; + set foo(value: number); +} + +declare class C2 { + get foo(): number; + protected set foo(value: number); +} + +declare class C3 { + protected get foo(): number; + protected set foo(value: number); +} + +// Unions properties have most restricted accessibility + +declare const cu12: C1 | C2; +cu12.foo; +cu12.foo = 123; // Error + +declare const cu13: C1 | C3; +cu13.foo; // Error +cu13.foo = 123; // Error + +declare const cu22: C2 | C3; +cu13.foo; // Error +cu13.foo = 123; // Error + +// Intersection properties have most permissive accessibility + +declare const ci12: C1 & C2; +ci12.foo; +ci12.foo = 123; + +declare const ci13: C1 & C3; +ci12.foo; +ci12.foo = 123; + +declare const ci23: C2 & C3; +ci23.foo; +ci23.foo = 123; // Error From 56d619bfb2b139e881c7dbda4ed6ee5dca498821 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 23 Aug 2026 14:18:56 -0700 Subject: [PATCH 06/10] Fix union accessibility and error reporting on private properties --- tsc/internal/checker/checker.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 88ef07d76a724..dc2fc7d991a98 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -11922,10 +11922,14 @@ func (c *Checker) checkPropertyAccessibilityAtLocation(location *ast.Node, isSup // Property is known to be private or protected at this point // Private property is accessible if the property is within the declaring class if flags&ast.ModifierFlagsPrivate != 0 { - declaringClassDeclaration := ast.GetClassLikeDeclarationOfSymbol(c.getParentOfSymbol(prop)) - if !c.isNodeWithinClass(location, declaringClassDeclaration) { + var declaringClassDeclaration *ast.Node + if parent := c.getParentOfSymbol(prop); parent != nil { + declaringClassDeclaration = ast.GetClassLikeDeclarationOfSymbol(parent) + } + if declaringClassDeclaration == nil || !c.isNodeWithinClass(location, declaringClassDeclaration) { if errorNode != nil { - c.error(errorNode, diagnostics.Property_0_is_private_and_only_accessible_within_class_1, c.symbolToString(prop), c.TypeToString(c.getDeclaringClass(prop))) + class := core.OrElse(c.getDeclaringClass(prop), containingType) + c.error(errorNode, diagnostics.Property_0_is_private_and_only_accessible_within_class_1, c.symbolToString(prop), c.TypeToString(class)) } return false } @@ -11958,10 +11962,7 @@ func (c *Checker) checkPropertyAccessibilityAtLocation(location *ast.Node, isSup } if flags&ast.ModifierFlagsStatic != 0 || enclosingClass == nil { if errorNode != nil { - class := c.getDeclaringClass(prop) - if class == nil { - class = containingType - } + class := core.OrElse(c.getDeclaringClass(prop), containingType) c.error(errorNode, diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, c.symbolToString(prop), c.TypeToString(class)) } return false @@ -21685,8 +21686,8 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s if checkFlags&(ast.CheckFlagsContainsPrivate|ast.CheckFlagsContainsProtected) != 0 { return nil } - // If the private or protected declaration is for writing, we give the write-side of the property - // the most restrictive accessbility of the constituents. + // Otherwise, if the private or protected declaration is for writing, reduce accessibility to that of + // the most restricted constituent. if checkFlags&ast.CheckFlagsContainsWritePrivate != 0 { checkFlags &^= ast.CheckFlagsContainsWritePublic | ast.CheckFlagsContainsWriteProtected } else if checkFlags&ast.CheckFlagsContainsWriteProtected != 0 { From 9c9c51f2aa7d2bb4dfe6ac94cfd33881dca2b435 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 23 Aug 2026 14:19:20 -0700 Subject: [PATCH 07/10] Add more tests --- .../compiler/syntheticProtectedProperties.ts | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts index 7975e4f99e9ff..7bb293f26ca30 100644 --- a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts +++ b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts @@ -45,19 +45,46 @@ declare class C3 { protected set foo(value: number); } +declare class P1 { + get foo(): number; + set foo(value: number); +} + +declare class P2 { + get foo(): number; + private set foo(value: number); +} + +declare class P3 { + private get foo(): number; + private set foo(value: number); +} + // Unions properties have most restricted accessibility declare const cu12: C1 | C2; cu12.foo; -cu12.foo = 123; // Error +cu12.foo = 123; // Error, protected declare const cu13: C1 | C3; -cu13.foo; // Error -cu13.foo = 123; // Error +cu13.foo; // Error, no property +cu13.foo = 123; // Error, no property -declare const cu22: C2 | C3; -cu13.foo; // Error -cu13.foo = 123; // Error +declare const cu23: C2 | C3; +cu23.foo; // Error, no property +cu23.foo = 123; // Error, no property + +declare const pu12: P1 | P2; +pu12.foo; +pu12.foo = 123; // Error, private + +declare const pu13: P1 | P3; +pu13.foo; // Error, no property +pu13.foo = 123; // Error, no property + +declare const pu23: P2 | P3; +pu23.foo; // Error, no property +pu23.foo = 123; // Error, no property // Intersection properties have most permissive accessibility @@ -66,9 +93,21 @@ ci12.foo; ci12.foo = 123; declare const ci13: C1 & C3; -ci12.foo; -ci12.foo = 123; +ci13.foo; +ci13.foo = 123; declare const ci23: C2 & C3; ci23.foo; -ci23.foo = 123; // Error +ci23.foo = 123; // Error, protected + +declare const pi12: P1 & P2; +pi12.foo; +pi12.foo = 123; + +declare const pi13: P1 & P3; +pi13.foo; // Error, reduced to never +pi13.foo = 123; // Error, reduced to never + +declare const pi23: P2 & P3; +pi23.foo; // Error, reduced to never +pi23.foo = 123; // Error, reduced to never From b194b9d72a07d415b76cf1485489c94fd8ab759d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 23 Aug 2026 14:19:33 -0700 Subject: [PATCH 08/10] Accept new baselines --- .../syntheticProtectedProperties.errors.txt | 110 ++++++++++-- .../syntheticProtectedProperties.symbols | 169 ++++++++++++++---- .../syntheticProtectedProperties.types | 163 ++++++++++++++--- 3 files changed, 373 insertions(+), 69 deletions(-) diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt index 541729563e4d0..57504522a12bd 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt @@ -1,12 +1,25 @@ -syntheticProtectedProperties.ts(50,6): error TS2445: Property 'foo' is protected and only accessible within class 'C1 | C2' and its subclasses. -syntheticProtectedProperties.ts(53,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. -syntheticProtectedProperties.ts(54,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. -syntheticProtectedProperties.ts(57,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. -syntheticProtectedProperties.ts(58,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. -syntheticProtectedProperties.ts(72,6): error TS2445: Property 'foo' is protected and only accessible within class 'C2 & C3' and its subclasses. +syntheticProtectedProperties.ts(65,6): error TS2445: Property 'foo' is protected and only accessible within class 'C1 | C2' and its subclasses. +syntheticProtectedProperties.ts(68,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(69,6): error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +syntheticProtectedProperties.ts(72,6): error TS2339: Property 'foo' does not exist on type 'C2 | C3'. +syntheticProtectedProperties.ts(73,6): error TS2339: Property 'foo' does not exist on type 'C2 | C3'. +syntheticProtectedProperties.ts(77,6): error TS2341: Property 'foo' is private and only accessible within class 'P1 | P2'. +syntheticProtectedProperties.ts(80,6): error TS2339: Property 'foo' does not exist on type 'P1 | P3'. +syntheticProtectedProperties.ts(81,6): error TS2339: Property 'foo' does not exist on type 'P1 | P3'. +syntheticProtectedProperties.ts(84,6): error TS2339: Property 'foo' does not exist on type 'P2 | P3'. +syntheticProtectedProperties.ts(85,6): error TS2339: Property 'foo' does not exist on type 'P2 | P3'. +syntheticProtectedProperties.ts(99,6): error TS2445: Property 'foo' is protected and only accessible within class 'C2 & C3' and its subclasses. +syntheticProtectedProperties.ts(106,6): error TS2339: Property 'foo' does not exist on type 'never'. + The intersection 'P1 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. +syntheticProtectedProperties.ts(107,6): error TS2339: Property 'foo' does not exist on type 'never'. + The intersection 'P1 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. +syntheticProtectedProperties.ts(110,6): error TS2339: Property 'foo' does not exist on type 'never'. + The intersection 'P2 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. +syntheticProtectedProperties.ts(111,6): error TS2339: Property 'foo' does not exist on type 'never'. + The intersection 'P2 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. -==== syntheticProtectedProperties.ts (6 errors) ==== +==== syntheticProtectedProperties.ts (15 errors) ==== // https://github.com/microsoft/TypeScript/issues/63749 declare class Dummy { @@ -52,29 +65,66 @@ syntheticProtectedProperties.ts(72,6): error TS2445: Property 'foo' is protected protected set foo(value: number); } + declare class P1 { + get foo(): number; + set foo(value: number); + } + + declare class P2 { + get foo(): number; + private set foo(value: number); + } + + declare class P3 { + private get foo(): number; + private set foo(value: number); + } + // Unions properties have most restricted accessibility declare const cu12: C1 | C2; cu12.foo; - cu12.foo = 123; // Error + cu12.foo = 123; // Error, protected ~~~ !!! error TS2445: Property 'foo' is protected and only accessible within class 'C1 | C2' and its subclasses. declare const cu13: C1 | C3; - cu13.foo; // Error + cu13.foo; // Error, no property ~~~ !!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. - cu13.foo = 123; // Error + cu13.foo = 123; // Error, no property ~~~ !!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. - declare const cu22: C2 | C3; - cu13.foo; // Error + declare const cu23: C2 | C3; + cu23.foo; // Error, no property ~~~ -!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. - cu13.foo = 123; // Error +!!! error TS2339: Property 'foo' does not exist on type 'C2 | C3'. + cu23.foo = 123; // Error, no property ~~~ -!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. +!!! error TS2339: Property 'foo' does not exist on type 'C2 | C3'. + + declare const pu12: P1 | P2; + pu12.foo; + pu12.foo = 123; // Error, private + ~~~ +!!! error TS2341: Property 'foo' is private and only accessible within class 'P1 | P2'. + + declare const pu13: P1 | P3; + pu13.foo; // Error, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'P1 | P3'. + pu13.foo = 123; // Error, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'P1 | P3'. + + declare const pu23: P2 | P3; + pu23.foo; // Error, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'P2 | P3'. + pu23.foo = 123; // Error, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'P2 | P3'. // Intersection properties have most permissive accessibility @@ -83,12 +133,36 @@ syntheticProtectedProperties.ts(72,6): error TS2445: Property 'foo' is protected ci12.foo = 123; declare const ci13: C1 & C3; - ci12.foo; - ci12.foo = 123; + ci13.foo; + ci13.foo = 123; declare const ci23: C2 & C3; ci23.foo; - ci23.foo = 123; // Error + ci23.foo = 123; // Error, protected ~~~ !!! error TS2445: Property 'foo' is protected and only accessible within class 'C2 & C3' and its subclasses. + + declare const pi12: P1 & P2; + pi12.foo; + pi12.foo = 123; + + declare const pi13: P1 & P3; + pi13.foo; // Error, reduced to never + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'never'. +!!! error TS2339: The intersection 'P1 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. + pi13.foo = 123; // Error, reduced to never + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'never'. +!!! error TS2339: The intersection 'P1 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. + + declare const pi23: P2 & P3; + pi23.foo; // Error, reduced to never + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'never'. +!!! error TS2339: The intersection 'P2 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. + pi23.foo = 123; // Error, reduced to never + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'never'. +!!! error TS2339: The intersection 'P2 & P3' was reduced to 'never' because property 'foo' exists in multiple constituents and is private in some. \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols index bc08d9aa06dec..85797ad73c28d 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols @@ -105,89 +105,196 @@ declare class C3 { >value : Symbol(value, Decl(syntheticProtectedProperties.ts, 42, 22)) } +declare class P1 { +>P1 : Symbol(P1, Decl(syntheticProtectedProperties.ts, 43, 1)) + + get foo(): number; +>foo : Symbol(P1.foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22)) + + set foo(value: number); +>foo : Symbol(P1.foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 47, 12)) +} + +declare class P2 { +>P2 : Symbol(P2, Decl(syntheticProtectedProperties.ts, 48, 1)) + + get foo(): number; +>foo : Symbol(P2.foo, Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) + + private set foo(value: number); +>foo : Symbol(P2.foo, Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 52, 20)) +} + +declare class P3 { +>P3 : Symbol(P3, Decl(syntheticProtectedProperties.ts, 53, 1)) + + private get foo(): number; +>foo : Symbol(P3.foo, Decl(syntheticProtectedProperties.ts, 55, 18), Decl(syntheticProtectedProperties.ts, 56, 30)) + + private set foo(value: number); +>foo : Symbol(P3.foo, Decl(syntheticProtectedProperties.ts, 55, 18), Decl(syntheticProtectedProperties.ts, 56, 30)) +>value : Symbol(value, Decl(syntheticProtectedProperties.ts, 57, 20)) +} + // Unions properties have most restricted accessibility declare const cu12: C1 | C2; ->cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 62, 13)) >C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) >C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) cu12.foo; >cu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 62, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) -cu12.foo = 123; // Error +cu12.foo = 123; // Error, protected >cu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 47, 13)) +>cu12 : Symbol(cu12, Decl(syntheticProtectedProperties.ts, 62, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) declare const cu13: C1 | C3; ->cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 66, 13)) >C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) >C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) -cu13.foo; // Error ->cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +cu13.foo; // Error, no property +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 66, 13)) -cu13.foo = 123; // Error ->cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +cu13.foo = 123; // Error, no property +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 66, 13)) -declare const cu22: C2 | C3; ->cu22 : Symbol(cu22, Decl(syntheticProtectedProperties.ts, 55, 13)) +declare const cu23: C2 | C3; +>cu23 : Symbol(cu23, Decl(syntheticProtectedProperties.ts, 70, 13)) >C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) >C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) -cu13.foo; // Error ->cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +cu23.foo; // Error, no property +>cu23 : Symbol(cu23, Decl(syntheticProtectedProperties.ts, 70, 13)) + +cu23.foo = 123; // Error, no property +>cu23 : Symbol(cu23, Decl(syntheticProtectedProperties.ts, 70, 13)) + +declare const pu12: P1 | P2; +>pu12 : Symbol(pu12, Decl(syntheticProtectedProperties.ts, 74, 13)) +>P1 : Symbol(P1, Decl(syntheticProtectedProperties.ts, 43, 1)) +>P2 : Symbol(P2, Decl(syntheticProtectedProperties.ts, 48, 1)) + +pu12.foo; +>pu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) +>pu12 : Symbol(pu12, Decl(syntheticProtectedProperties.ts, 74, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) + +pu12.foo = 123; // Error, private +>pu12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) +>pu12 : Symbol(pu12, Decl(syntheticProtectedProperties.ts, 74, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) + +declare const pu13: P1 | P3; +>pu13 : Symbol(pu13, Decl(syntheticProtectedProperties.ts, 78, 13)) +>P1 : Symbol(P1, Decl(syntheticProtectedProperties.ts, 43, 1)) +>P3 : Symbol(P3, Decl(syntheticProtectedProperties.ts, 53, 1)) -cu13.foo = 123; // Error ->cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 51, 13)) +pu13.foo; // Error, no property +>pu13 : Symbol(pu13, Decl(syntheticProtectedProperties.ts, 78, 13)) + +pu13.foo = 123; // Error, no property +>pu13 : Symbol(pu13, Decl(syntheticProtectedProperties.ts, 78, 13)) + +declare const pu23: P2 | P3; +>pu23 : Symbol(pu23, Decl(syntheticProtectedProperties.ts, 82, 13)) +>P2 : Symbol(P2, Decl(syntheticProtectedProperties.ts, 48, 1)) +>P3 : Symbol(P3, Decl(syntheticProtectedProperties.ts, 53, 1)) + +pu23.foo; // Error, no property +>pu23 : Symbol(pu23, Decl(syntheticProtectedProperties.ts, 82, 13)) + +pu23.foo = 123; // Error, no property +>pu23 : Symbol(pu23, Decl(syntheticProtectedProperties.ts, 82, 13)) // Intersection properties have most permissive accessibility declare const ci12: C1 & C2; ->ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 88, 13)) >C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) >C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) ci12.foo; >ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 88, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ci12.foo = 123; >ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) +>ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 88, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) declare const ci13: C1 & C3; ->ci13 : Symbol(ci13, Decl(syntheticProtectedProperties.ts, 65, 13)) +>ci13 : Symbol(ci13, Decl(syntheticProtectedProperties.ts, 92, 13)) >C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) >C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) -ci12.foo; ->ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) ->foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +ci13.foo; +>ci13.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +>ci13 : Symbol(ci13, Decl(syntheticProtectedProperties.ts, 92, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) -ci12.foo = 123; ->ci12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) ->ci12 : Symbol(ci12, Decl(syntheticProtectedProperties.ts, 61, 13)) ->foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22)) +ci13.foo = 123; +>ci13.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +>ci13 : Symbol(ci13, Decl(syntheticProtectedProperties.ts, 92, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 30, 18), Decl(syntheticProtectedProperties.ts, 31, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) declare const ci23: C2 & C3; ->ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 96, 13)) >C2 : Symbol(C2, Decl(syntheticProtectedProperties.ts, 33, 1)) >C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) ci23.foo; >ci23.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) ->ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 96, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) -ci23.foo = 123; // Error +ci23.foo = 123; // Error, protected >ci23.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) ->ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 69, 13)) +>ci23 : Symbol(ci23, Decl(syntheticProtectedProperties.ts, 96, 13)) >foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 35, 18), Decl(syntheticProtectedProperties.ts, 36, 22), Decl(syntheticProtectedProperties.ts, 40, 18), Decl(syntheticProtectedProperties.ts, 41, 32)) +declare const pi12: P1 & P2; +>pi12 : Symbol(pi12, Decl(syntheticProtectedProperties.ts, 100, 13)) +>P1 : Symbol(P1, Decl(syntheticProtectedProperties.ts, 43, 1)) +>P2 : Symbol(P2, Decl(syntheticProtectedProperties.ts, 48, 1)) + +pi12.foo; +>pi12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) +>pi12 : Symbol(pi12, Decl(syntheticProtectedProperties.ts, 100, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) + +pi12.foo = 123; +>pi12.foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) +>pi12 : Symbol(pi12, Decl(syntheticProtectedProperties.ts, 100, 13)) +>foo : Symbol(foo, Decl(syntheticProtectedProperties.ts, 45, 18), Decl(syntheticProtectedProperties.ts, 46, 22), Decl(syntheticProtectedProperties.ts, 50, 18), Decl(syntheticProtectedProperties.ts, 51, 22)) + +declare const pi13: P1 & P3; +>pi13 : Symbol(pi13, Decl(syntheticProtectedProperties.ts, 104, 13)) +>P1 : Symbol(P1, Decl(syntheticProtectedProperties.ts, 43, 1)) +>P3 : Symbol(P3, Decl(syntheticProtectedProperties.ts, 53, 1)) + +pi13.foo; // Error, reduced to never +>pi13 : Symbol(pi13, Decl(syntheticProtectedProperties.ts, 104, 13)) + +pi13.foo = 123; // Error, reduced to never +>pi13 : Symbol(pi13, Decl(syntheticProtectedProperties.ts, 104, 13)) + +declare const pi23: P2 & P3; +>pi23 : Symbol(pi23, Decl(syntheticProtectedProperties.ts, 108, 13)) +>P2 : Symbol(P2, Decl(syntheticProtectedProperties.ts, 48, 1)) +>P3 : Symbol(P3, Decl(syntheticProtectedProperties.ts, 53, 1)) + +pi23.foo; // Error, reduced to never +>pi23 : Symbol(pi23, Decl(syntheticProtectedProperties.ts, 108, 13)) + +pi23.foo = 123; // Error, reduced to never +>pi23 : Symbol(pi23, Decl(syntheticProtectedProperties.ts, 108, 13)) + diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types index efc6630d9757f..9d40cbc76fa03 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types @@ -99,6 +99,39 @@ declare class C3 { >value : number } +declare class P1 { +>P1 : P1 + + get foo(): number; +>foo : number + + set foo(value: number); +>foo : number +>value : number +} + +declare class P2 { +>P2 : P2 + + get foo(): number; +>foo : number + + private set foo(value: number); +>foo : number +>value : number +} + +declare class P3 { +>P3 : P3 + + private get foo(): number; +>foo : number + + private set foo(value: number); +>foo : number +>value : number +} + // Unions properties have most restricted accessibility declare const cu12: C1 | C2; @@ -109,7 +142,7 @@ cu12.foo; >cu12 : C1 | C2 >foo : number -cu12.foo = 123; // Error +cu12.foo = 123; // Error, protected >cu12.foo = 123 : 123 >cu12.foo : number >cu12 : C1 | C2 @@ -119,30 +152,75 @@ cu12.foo = 123; // Error declare const cu13: C1 | C3; >cu13 : C1 | C3 -cu13.foo; // Error +cu13.foo; // Error, no property >cu13.foo : any >cu13 : C1 | C3 >foo : any -cu13.foo = 123; // Error +cu13.foo = 123; // Error, no property >cu13.foo = 123 : 123 >cu13.foo : any >cu13 : C1 | C3 >foo : any >123 : 123 -declare const cu22: C2 | C3; ->cu22 : C2 | C3 +declare const cu23: C2 | C3; +>cu23 : C2 | C3 -cu13.foo; // Error ->cu13.foo : any ->cu13 : C1 | C3 +cu23.foo; // Error, no property +>cu23.foo : any +>cu23 : C2 | C3 >foo : any -cu13.foo = 123; // Error ->cu13.foo = 123 : 123 ->cu13.foo : any ->cu13 : C1 | C3 +cu23.foo = 123; // Error, no property +>cu23.foo = 123 : 123 +>cu23.foo : any +>cu23 : C2 | C3 +>foo : any +>123 : 123 + +declare const pu12: P1 | P2; +>pu12 : P1 | P2 + +pu12.foo; +>pu12.foo : number +>pu12 : P1 | P2 +>foo : number + +pu12.foo = 123; // Error, private +>pu12.foo = 123 : 123 +>pu12.foo : number +>pu12 : P1 | P2 +>foo : number +>123 : 123 + +declare const pu13: P1 | P3; +>pu13 : P1 | P3 + +pu13.foo; // Error, no property +>pu13.foo : any +>pu13 : P1 | P3 +>foo : any + +pu13.foo = 123; // Error, no property +>pu13.foo = 123 : 123 +>pu13.foo : any +>pu13 : P1 | P3 +>foo : any +>123 : 123 + +declare const pu23: P2 | P3; +>pu23 : P2 | P3 + +pu23.foo; // Error, no property +>pu23.foo : any +>pu23 : P2 | P3 +>foo : any + +pu23.foo = 123; // Error, no property +>pu23.foo = 123 : 123 +>pu23.foo : any +>pu23 : P2 | P3 >foo : any >123 : 123 @@ -166,15 +244,15 @@ ci12.foo = 123; declare const ci13: C1 & C3; >ci13 : C1 & C3 -ci12.foo; ->ci12.foo : number ->ci12 : C1 & C2 +ci13.foo; +>ci13.foo : number +>ci13 : C1 & C3 >foo : number -ci12.foo = 123; ->ci12.foo = 123 : 123 ->ci12.foo : number ->ci12 : C1 & C2 +ci13.foo = 123; +>ci13.foo = 123 : 123 +>ci13.foo : number +>ci13 : C1 & C3 >foo : number >123 : 123 @@ -186,10 +264,55 @@ ci23.foo; >ci23 : C2 & C3 >foo : number -ci23.foo = 123; // Error +ci23.foo = 123; // Error, protected >ci23.foo = 123 : 123 >ci23.foo : number >ci23 : C2 & C3 >foo : number >123 : 123 +declare const pi12: P1 & P2; +>pi12 : P1 & P2 + +pi12.foo; +>pi12.foo : number +>pi12 : P1 & P2 +>foo : number + +pi12.foo = 123; +>pi12.foo = 123 : 123 +>pi12.foo : number +>pi12 : P1 & P2 +>foo : number +>123 : 123 + +declare const pi13: P1 & P3; +>pi13 : never + +pi13.foo; // Error, reduced to never +>pi13.foo : any +>pi13 : never +>foo : any + +pi13.foo = 123; // Error, reduced to never +>pi13.foo = 123 : 123 +>pi13.foo : any +>pi13 : never +>foo : any +>123 : 123 + +declare const pi23: P2 & P3; +>pi23 : never + +pi23.foo; // Error, reduced to never +>pi23.foo : any +>pi23 : never +>foo : any + +pi23.foo = 123; // Error, reduced to never +>pi23.foo = 123 : 123 +>pi23.foo : any +>pi23 : never +>foo : any +>123 : 123 + From 01561734c0c9dedda297f7ff337f3c856d6ac1f9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 23 Aug 2026 14:33:11 -0700 Subject: [PATCH 09/10] Generate enums --- .../typescript/src/enums/checkFlags.enum.ts | 29 ++++++++++--------- packages/typescript/src/enums/checkFlags.ts | 29 ++++++++++--------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/packages/typescript/src/enums/checkFlags.enum.ts b/packages/typescript/src/enums/checkFlags.enum.ts index 7f27dc201db7b..7aab3deb385bf 100644 --- a/packages/typescript/src/enums/checkFlags.enum.ts +++ b/packages/typescript/src/enums/checkFlags.enum.ts @@ -13,19 +13,22 @@ export enum CheckFlags { ContainsPublic = 1 << 8, ContainsProtected = 1 << 9, ContainsPrivate = 1 << 10, - ContainsStatic = 1 << 11, - Late = 1 << 12, - ReverseMapped = 1 << 13, - OptionalParameter = 1 << 14, - RestParameter = 1 << 15, - DeferredType = 1 << 16, - HasNeverType = 1 << 17, - Mapped = 1 << 18, - StripOptional = 1 << 19, - Unresolved = 1 << 20, - IsDiscriminantComputed = 1 << 21, - IsDiscriminant = 1 << 22, - IndexSymbol = 1 << 23, + ContainsWritePublic = 1 << 11, + ContainsWriteProtected = 1 << 12, + ContainsWritePrivate = 1 << 13, + ContainsStatic = 1 << 14, + Late = 1 << 15, + ReverseMapped = 1 << 16, + OptionalParameter = 1 << 17, + RestParameter = 1 << 18, + DeferredType = 1 << 19, + HasNeverType = 1 << 20, + Mapped = 1 << 21, + StripOptional = 1 << 22, + Unresolved = 1 << 23, + IsDiscriminantComputed = 1 << 24, + IsDiscriminant = 1 << 25, + IndexSymbol = 1 << 26, Synthetic = SyntheticProperty | SyntheticMethod, NonUniformAndLiteral = HasNonUniformType | HasLiteralType, Partial = ReadPartial | WritePartial, diff --git a/packages/typescript/src/enums/checkFlags.ts b/packages/typescript/src/enums/checkFlags.ts index be3165fc706d5..8dfcbdb384974 100644 --- a/packages/typescript/src/enums/checkFlags.ts +++ b/packages/typescript/src/enums/checkFlags.ts @@ -13,19 +13,22 @@ export var CheckFlags: any; CheckFlags[CheckFlags["ContainsPublic"] = 256] = "ContainsPublic"; CheckFlags[CheckFlags["ContainsProtected"] = 512] = "ContainsProtected"; CheckFlags[CheckFlags["ContainsPrivate"] = 1024] = "ContainsPrivate"; - CheckFlags[CheckFlags["ContainsStatic"] = 2048] = "ContainsStatic"; - CheckFlags[CheckFlags["Late"] = 4096] = "Late"; - CheckFlags[CheckFlags["ReverseMapped"] = 8192] = "ReverseMapped"; - CheckFlags[CheckFlags["OptionalParameter"] = 16384] = "OptionalParameter"; - CheckFlags[CheckFlags["RestParameter"] = 32768] = "RestParameter"; - CheckFlags[CheckFlags["DeferredType"] = 65536] = "DeferredType"; - CheckFlags[CheckFlags["HasNeverType"] = 131072] = "HasNeverType"; - CheckFlags[CheckFlags["Mapped"] = 262144] = "Mapped"; - CheckFlags[CheckFlags["StripOptional"] = 524288] = "StripOptional"; - CheckFlags[CheckFlags["Unresolved"] = 1048576] = "Unresolved"; - CheckFlags[CheckFlags["IsDiscriminantComputed"] = 2097152] = "IsDiscriminantComputed"; - CheckFlags[CheckFlags["IsDiscriminant"] = 4194304] = "IsDiscriminant"; - CheckFlags[CheckFlags["IndexSymbol"] = 8388608] = "IndexSymbol"; + CheckFlags[CheckFlags["ContainsWritePublic"] = 2048] = "ContainsWritePublic"; + CheckFlags[CheckFlags["ContainsWriteProtected"] = 4096] = "ContainsWriteProtected"; + CheckFlags[CheckFlags["ContainsWritePrivate"] = 8192] = "ContainsWritePrivate"; + CheckFlags[CheckFlags["ContainsStatic"] = 16384] = "ContainsStatic"; + CheckFlags[CheckFlags["Late"] = 32768] = "Late"; + CheckFlags[CheckFlags["ReverseMapped"] = 65536] = "ReverseMapped"; + CheckFlags[CheckFlags["OptionalParameter"] = 131072] = "OptionalParameter"; + CheckFlags[CheckFlags["RestParameter"] = 262144] = "RestParameter"; + CheckFlags[CheckFlags["DeferredType"] = 524288] = "DeferredType"; + CheckFlags[CheckFlags["HasNeverType"] = 1048576] = "HasNeverType"; + CheckFlags[CheckFlags["Mapped"] = 2097152] = "Mapped"; + CheckFlags[CheckFlags["StripOptional"] = 4194304] = "StripOptional"; + CheckFlags[CheckFlags["Unresolved"] = 8388608] = "Unresolved"; + CheckFlags[CheckFlags["IsDiscriminantComputed"] = 16777216] = "IsDiscriminantComputed"; + CheckFlags[CheckFlags["IsDiscriminant"] = 33554432] = "IsDiscriminant"; + CheckFlags[CheckFlags["IndexSymbol"] = 67108864] = "IndexSymbol"; CheckFlags[CheckFlags["Synthetic"] = 6] = "Synthetic"; CheckFlags[CheckFlags["NonUniformAndLiteral"] = 192] = "NonUniformAndLiteral"; CheckFlags[CheckFlags["Partial"] = 48] = "Partial"; From 78fc649dbb7acd877b4f1e8e31a5b1c1c3b34b4b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 23 Aug 2026 18:47:36 -0700 Subject: [PATCH 10/10] Accept new baselines --- .../compiler/syntheticProtectedProperties.symbols | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols index 85797ad73c28d..25260556ee2f5 100644 --- a/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols @@ -46,9 +46,9 @@ if (w instanceof Mock) { >Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) w.content; ->w.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) >w : Symbol(w, Decl(syntheticProtectedProperties.ts, 18, 13)) ->content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) } declare const w2: Mock & Public >w2 : Symbol(w2, Decl(syntheticProtectedProperties.ts, 22, 13)) @@ -56,9 +56,9 @@ declare const w2: Mock & Public >Public : Symbol(Public, Decl(syntheticProtectedProperties.ts, 4, 1)) w2.content; ->w2.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w2.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36)) >w2 : Symbol(w2, Decl(syntheticProtectedProperties.ts, 22, 13)) ->content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36)) declare const w3: Public & Mock >w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 25, 13)) @@ -66,9 +66,9 @@ declare const w3: Public & Mock >Mock : Symbol(Mock, Decl(syntheticProtectedProperties.ts, 11, 1)) w3.content; ->w3.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>w3.content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) >w3 : Symbol(w3, Decl(syntheticProtectedProperties.ts, 25, 13)) ->content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26), Decl(syntheticProtectedProperties.ts, 13, 20) ... and 1 more) +>content : Symbol(Mock.content, Decl(syntheticProtectedProperties.ts, 8, 20), Decl(syntheticProtectedProperties.ts, 9, 36), Decl(syntheticProtectedProperties.ts, 13, 20), Decl(syntheticProtectedProperties.ts, 14, 26)) // private/protected set accessors are tracked in unions and intersections