@@ -467,6 +467,7 @@ import {
467
467
IntroducesNewScopeNode,
468
468
isAccessExpression,
469
469
isAccessor,
470
+ isAccessorModifier,
470
471
isAliasableExpression,
471
472
isAmbientModule,
472
473
isArray,
@@ -7690,27 +7691,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
7690
7691
7691
7692
if (propertySymbol.flags & SymbolFlags.Accessor) {
7692
7693
const writeType = getWriteTypeOfSymbol(propertySymbol);
7693
- if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) {
7694
+ if (!isErrorType(propertyType) && !isErrorType(writeType)) {
7694
7695
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
+ }
7714
7739
}
7715
7740
}
7716
7741
@@ -12816,13 +12841,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
12816
12841
*/
12817
12842
function getWriteTypeOfSymbol(symbol: Symbol): Type {
12818
12843
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
+ }
12819
12850
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));
12826
12852
}
12827
12853
if (symbol.flags & SymbolFlags.Accessor) {
12828
12854
return checkFlags & CheckFlags.Instantiated ?
@@ -15439,6 +15465,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15439
15465
}
15440
15466
15441
15467
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined {
15468
+ let propFlags = SymbolFlags.None;
15442
15469
let singleProp: Symbol | undefined;
15443
15470
let propSet: Map<SymbolId, Symbol> | undefined;
15444
15471
let indexTypes: Type[] | undefined;
@@ -15465,6 +15492,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15465
15492
}
15466
15493
if (!singleProp) {
15467
15494
singleProp = prop;
15495
+ propFlags = (prop.flags & SymbolFlags.Accessor) || SymbolFlags.Property;
15468
15496
}
15469
15497
else if (prop !== singleProp) {
15470
15498
const isInstantiation = (getTargetSymbol(prop) || prop) === (getTargetSymbol(singleProp) || singleProp);
@@ -15487,6 +15515,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15487
15515
propSet.set(id, prop);
15488
15516
}
15489
15517
}
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
+ }
15490
15525
}
15491
15526
if (isUnion && isReadonlySymbol(prop)) {
15492
15527
checkFlags |= CheckFlags.Readonly;
@@ -15505,6 +15540,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15505
15540
else if (isUnion) {
15506
15541
const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name);
15507
15542
if (indexInfo) {
15543
+ propFlags = (propFlags & ~SymbolFlags.Accessor) | SymbolFlags.Property;
15508
15544
checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0);
15509
15545
indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type);
15510
15546
}
@@ -15583,7 +15619,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
15583
15619
propTypes.push(type);
15584
15620
}
15585
15621
addRange(propTypes, indexTypes);
15586
- const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
15622
+ const result = createSymbol(propFlags | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
15587
15623
result.links.containingType = containingType;
15588
15624
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
15589
15625
result.valueDeclaration = firstValueDeclaration;
0 commit comments