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"; 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 ba4c3fa2718b6..9c9cb64c78a31 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 @@ -21585,6 +21586,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 +21626,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 @@ -21665,13 +21672,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 + } + // 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 { + checkFlags &^= ast.CheckFlagsContainsWritePublic + } } if propSet.Size() == 0 && checkFlags&ast.CheckFlagsReadPartial == 0 && len(indexTypes) == 0 { if !mergedInstantiations { diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 69b2362c8fb58..9c486a5bb90ab 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -715,6 +715,21 @@ 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 !isWrite && s.CheckFlags&ast.CheckFlagsContainsPublic != 0 || isWrite && s.CheckFlags&ast.CheckFlagsContainsWritePublic != 0: + accessModifier = ast.ModifierFlagsPublic + 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 + } + if s.CheckFlags&ast.CheckFlagsContainsStatic != 0 { + return accessModifier | ast.ModifierFlagsStatic + } + return accessModifier + } if s.ValueDeclaration != nil { var declaration *ast.Node if isWrite { @@ -732,22 +747,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 } 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..57504522a12bd --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.errors.txt @@ -0,0 +1,168 @@ +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 (15 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); + } + + 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, 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, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + cu13.foo = 123; // Error, no property + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'C1 | C3'. + + declare const cu23: C2 | C3; + cu23.foo; // Error, no property + ~~~ +!!! 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 '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 + + declare const ci12: C1 & C2; + ci12.foo; + ci12.foo = 123; + + declare const ci13: C1 & C3; + ci13.foo; + ci13.foo = 123; + + declare const ci23: C2 & C3; + ci23.foo; + 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 new file mode 100644 index 0000000000000..25260556ee2f5 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.symbols @@ -0,0 +1,300 @@ +//// [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)) +>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)) +} +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)) +>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)) + +declare const w3: Public & Mock +>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)) +>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)) + +// 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)) +} + +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, 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, 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, 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, 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, 66, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +cu13.foo; // Error, no property +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 66, 13)) + +cu13.foo = 123; // Error, no property +>cu13 : Symbol(cu13, Decl(syntheticProtectedProperties.ts, 66, 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)) + +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)) + +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, 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, 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, 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, 92, 13)) +>C1 : Symbol(C1, Decl(syntheticProtectedProperties.ts, 26, 11)) +>C3 : Symbol(C3, Decl(syntheticProtectedProperties.ts, 38, 1)) + +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)) + +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, 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, 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, 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, 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 new file mode 100644 index 0000000000000..9d40cbc76fa03 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/syntheticProtectedProperties.types @@ -0,0 +1,318 @@ +//// [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 + +// 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 +} + +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; +>cu12 : C1 | C2 + +cu12.foo; +>cu12.foo : number +>cu12 : C1 | C2 +>foo : number + +cu12.foo = 123; // Error, protected +>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, no property +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any + +cu13.foo = 123; // Error, no property +>cu13.foo = 123 : 123 +>cu13.foo : any +>cu13 : C1 | C3 +>foo : any +>123 : 123 + +declare const cu23: C2 | C3; +>cu23 : C2 | C3 + +cu23.foo; // Error, no property +>cu23.foo : any +>cu23 : C2 | C3 +>foo : any + +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 + +// 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 + +ci13.foo; +>ci13.foo : number +>ci13 : C1 & C3 +>foo : number + +ci13.foo = 123; +>ci13.foo = 123 : 123 +>ci13.foo : number +>ci13 : C1 & C3 +>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, 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 + diff --git a/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts new file mode 100644 index 0000000000000..7bb293f26ca30 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/syntheticProtectedProperties.ts @@ -0,0 +1,113 @@ +// @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; + +// 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); +} + +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, protected + +declare const cu13: C1 | C3; +cu13.foo; // Error, no property +cu13.foo = 123; // Error, no property + +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 + +declare const ci12: C1 & C2; +ci12.foo; +ci12.foo = 123; + +declare const ci13: C1 & C3; +ci13.foo; +ci13.foo = 123; + +declare const ci23: C2 & C3; +ci23.foo; +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