From 3bb8f5893656c07678ad11aefc6cafe31ff03728 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 20 Aug 2026 13:19:56 -0700 Subject: [PATCH 1/2] 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 2/2] 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;