@@ -467,6 +467,7 @@ import {
467467 IntroducesNewScopeNode,
468468 isAccessExpression,
469469 isAccessor,
470+ isAccessorModifier,
470471 isAliasableExpression,
471472 isAmbientModule,
472473 isArray,
@@ -7690,27 +7691,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
76907691
76917692 if (propertySymbol.flags & SymbolFlags.Accessor) {
76927693 const writeType = getWriteTypeOfSymbol(propertySymbol);
7693- if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) {
7694+ if (!isErrorType(propertyType) && !isErrorType(writeType)) {
76947695 const symbolMapper = getSymbolLinks(propertySymbol).mapper;
7695- const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor)!;
7696- const getterSignature = getSignatureFromDeclaration(getterDeclaration);
7697- typeElements.push(
7698- setCommentRange(
7699- context,
7700- signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(getterSignature, symbolMapper) : getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7701- getterDeclaration,
7702- ),
7703- );
7704- const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor)!;
7705- const setterSignature = getSignatureFromDeclaration(setterDeclaration);
7706- typeElements.push(
7707- setCommentRange(
7708- context,
7709- signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(setterSignature, symbolMapper) : setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7710- setterDeclaration,
7711- ),
7712- );
7713- return;
7696+ const propDeclaration = getDeclarationOfKind<PropertyDeclaration>(propertySymbol, SyntaxKind.PropertyDeclaration);
7697+ if (propertyType !== writeType || propertySymbol.parent!.flags & SymbolFlags.Class && !propDeclaration) {
7698+ const getterDeclaration = getDeclarationOfKind<GetAccessorDeclaration>(propertySymbol, SyntaxKind.GetAccessor);
7699+ if (getterDeclaration) {
7700+ const getterSignature = getSignatureFromDeclaration(getterDeclaration);
7701+ typeElements.push(
7702+ setCommentRange(
7703+ context,
7704+ signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(getterSignature, symbolMapper) : getterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7705+ getterDeclaration,
7706+ ),
7707+ );
7708+ }
7709+ const setterDeclaration = getDeclarationOfKind<SetAccessorDeclaration>(propertySymbol, SyntaxKind.SetAccessor);
7710+ if (setterDeclaration) {
7711+ const setterSignature = getSignatureFromDeclaration(setterDeclaration);
7712+ typeElements.push(
7713+ setCommentRange(
7714+ context,
7715+ signatureToSignatureDeclarationHelper(symbolMapper ? instantiateSignature(setterSignature, symbolMapper) : setterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7716+ setterDeclaration,
7717+ ),
7718+ );
7719+ }
7720+ return;
7721+ }
7722+ if (propertySymbol.parent!.flags & SymbolFlags.Class && propDeclaration && find(propDeclaration.modifiers, isAccessorModifier)) {
7723+ const fakeGetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, emptyArray, propertyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
7724+ typeElements.push(
7725+ setCommentRange(
7726+ context,
7727+ signatureToSignatureDeclarationHelper(fakeGetterSignature, SyntaxKind.GetAccessor, context, { name: propertyName }) as GetAccessorDeclaration,
7728+ propDeclaration,
7729+ ),
7730+ );
7731+ const setterParam = createSymbol(SymbolFlags.FunctionScopedVariable, "arg" as __String);
7732+ setterParam.links.type = writeType;
7733+ const fakeSetterSignature = createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, [setterParam], voidType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None);
7734+ typeElements.push(
7735+ signatureToSignatureDeclarationHelper(fakeSetterSignature, SyntaxKind.SetAccessor, context, { name: propertyName }) as SetAccessorDeclaration,
7736+ );
7737+ return;
7738+ }
77147739 }
77157740 }
77167741
@@ -12816,13 +12841,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1281612841 */
1281712842 function getWriteTypeOfSymbol(symbol: Symbol): Type {
1281812843 const checkFlags = getCheckFlags(symbol);
12844+ if (checkFlags & CheckFlags.SyntheticProperty) {
12845+ return checkFlags & CheckFlags.DeferredType ?
12846+ getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
12847+ // NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty
12848+ (symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type!;
12849+ }
1281912850 if (symbol.flags & SymbolFlags.Property) {
12820- return checkFlags & CheckFlags.SyntheticProperty ?
12821- checkFlags & CheckFlags.DeferredType ?
12822- getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) :
12823- // NOTE: cast to TransientSymbol should be safe because only TransientSymbols can have CheckFlags.SyntheticProperty
12824- (symbol as TransientSymbol).links.writeType || (symbol as TransientSymbol).links.type! :
12825- removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
12851+ return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
1282612852 }
1282712853 if (symbol.flags & SymbolFlags.Accessor) {
1282812854 return checkFlags & CheckFlags.Instantiated ?
@@ -15439,6 +15465,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1543915465 }
1544015466
1544115467 function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
15468+ let propFlags = SymbolFlags.None;
1544215469 let singleProp: Symbol | undefined;
1544315470 let propSet: Map<SymbolId, Symbol> | undefined;
1544415471 let indexTypes: Type[] | undefined;
@@ -15465,6 +15492,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1546515492 }
1546615493 if (!singleProp) {
1546715494 singleProp = prop;
15495+ propFlags = (prop.flags & SymbolFlags.Accessor) || SymbolFlags.Property;
1546815496 }
1546915497 else if (prop !== singleProp) {
1547015498 const isInstantiation = (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp);
@@ -15487,6 +15515,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1548715515 propSet.set(id, prop);
1548815516 }
1548915517 }
15518+ // classes created by mixins are represented as intersections
15519+ // and overriding a property in a derived class redefines it completely at runtime
15520+ // so a get accessor can't be merged with a set accessor in a base class,
15521+ // for that reason the accessor flags are only used when they are the same in all constituents
15522+ if (propFlags & SymbolFlags.Accessor && (prop.flags & SymbolFlags.Accessor) !== (propFlags & SymbolFlags.Accessor)) {
15523+ propFlags = (propFlags & ~SymbolFlags.Accessor) | SymbolFlags.Property;
15524+ }
1549015525 }
1549115526 if (isUnion && isReadonlySymbol(prop)) {
1549215527 checkFlags |= CheckFlags.Readonly;
@@ -15505,6 +15540,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1550515540 else if (isUnion) {
1550615541 const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name);
1550715542 if (indexInfo) {
15543+ propFlags = (propFlags & ~SymbolFlags.Accessor) | SymbolFlags.Property;
1550815544 checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0);
1550915545 indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type);
1551015546 }
@@ -15583,7 +15619,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1558315619 propTypes.push(type);
1558415620 }
1558515621 addRange(propTypes, indexTypes);
15586- const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
15622+ const result = createSymbol(propFlags | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
1558715623 result.links.containingType = containingType;
1558815624 if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
1558915625 result.valueDeclaration = firstValueDeclaration;
0 commit comments