@@ -25967,10 +25967,18 @@ namespace ts {
25967
25967
*/
25968
25968
function checkPropertyAccessibility(
25969
25969
node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement,
25970
- isSuper: boolean, type: Type, prop: Symbol): boolean {
25971
- const flags = getDeclarationModifierFlagsFromSymbol(prop);
25970
+ isSuper: boolean, type: Type, prop: Symbol, isWrite = false ): boolean {
25971
+ let flags = getDeclarationModifierFlagsFromSymbol(prop);
25972
25972
const errorNode = node.kind === SyntaxKind.QualifiedName ? node.right : node.kind === SyntaxKind.ImportType ? node : node.name;
25973
25973
25974
+ // Writes use the visibility modifier of the set accessor, if one is declared
25975
+ if (isWrite) {
25976
+ const setter = forEach(prop.declarations, p => p.kind === SyntaxKind.SetAccessor && p);
25977
+ if (setter) {
25978
+ flags = (flags & ~ModifierFlags.AccessibilityModifier) | getEffectiveDeclarationFlags(setter, ModifierFlags.AccessibilityModifier);
25979
+ }
25980
+ }
25981
+
25974
25982
if (isSuper) {
25975
25983
// TS 1.0 spec (April 2014): 4.8.2
25976
25984
// - In a constructor, instance member function, instance member accessor, or
@@ -26285,7 +26293,7 @@ namespace ts {
26285
26293
markAliasReferenced(parentSymbol, node);
26286
26294
}
26287
26295
26288
- let propType: Type;
26296
+ let propType: Type | undefined ;
26289
26297
if (!prop) {
26290
26298
const indexInfo = !isPrivateIdentifier(right) && (assignmentKind === AssignmentKind.None || !isGenericObjectType(leftType) || isThisTypeParameter(leftType)) ? getIndexInfoOfType(apparentType, IndexKind.String) : undefined;
26291
26299
if (!(indexInfo && indexInfo.type)) {
@@ -26316,19 +26324,30 @@ namespace ts {
26316
26324
}
26317
26325
}
26318
26326
else {
26327
+ const isWrite = isWriteAccess(node);
26319
26328
if (getDeclarationNodeFlagsFromSymbol(prop) & NodeFlags.Deprecated && isUncalledFunctionReference(node, prop)) {
26320
26329
errorOrSuggestion(/* isError */ false, right, Diagnostics._0_is_deprecated, right.escapedText as string);
26321
26330
}
26322
26331
checkPropertyNotUsedBeforeDeclaration(prop, node, right);
26323
26332
markPropertyAsReferenced(prop, node, left.kind === SyntaxKind.ThisKeyword);
26324
26333
getNodeLinks(node).resolvedSymbol = prop;
26325
- checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, apparentType, prop);
26334
+ checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, apparentType, prop, isWrite );
26326
26335
if (isAssignmentToReadonlyEntity(node as Expression, prop, assignmentKind)) {
26327
26336
error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, idText(right));
26328
26337
return errorType;
26329
26338
}
26330
- propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : getConstraintForLocation(getTypeOfSymbol(prop), node);
26339
+ if (isWrite) {
26340
+ const setter = forEach(prop.declarations, p => (p.kind === SyntaxKind.SetAccessor && p));
26341
+ if (setter) {
26342
+ propType = getAnnotatedAccessorType(setter as SetAccessorDeclaration);
26343
+ }
26344
+ }
26345
+
26346
+ if (propType === undefined) {
26347
+ propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : getConstraintForLocation(getTypeOfSymbol(prop), node);
26348
+ }
26331
26349
}
26350
+ // For writes to properties declared as accessors, use the 'set' type
26332
26351
return getFlowTypeOfAccessExpression(node, prop, propType, right);
26333
26352
}
26334
26353
@@ -32321,15 +32340,19 @@ namespace ts {
32321
32340
const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
32322
32341
const otherAccessor = getDeclarationOfKind<AccessorDeclaration>(getSymbolOfNode(node), otherKind);
32323
32342
if (otherAccessor) {
32324
- const nodeFlags = getEffectiveModifierFlags(node);
32325
- const otherFlags = getEffectiveModifierFlags(otherAccessor);
32326
- if ((nodeFlags & ModifierFlags.Abstract) !== (otherFlags & ModifierFlags.Abstract)) {
32343
+ const getter = node.kind === SyntaxKind.GetAccessor ? node : otherAccessor;
32344
+ const setter = node.kind === SyntaxKind.SetAccessor ? node : otherAccessor;
32345
+ const getterFlags = getEffectiveModifierFlags(getter);
32346
+ const setterFlags = getEffectiveModifierFlags(setter);
32347
+ if ((getterFlags & ModifierFlags.Abstract) !== (setterFlags & ModifierFlags.Abstract)) {
32327
32348
error(node.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract);
32328
32349
}
32350
+ if (((getterFlags & ModifierFlags.Protected) && !(setterFlags & (ModifierFlags.Protected | ModifierFlags.Private))) ||
32351
+ ((getterFlags & ModifierFlags.Private) && !(setterFlags & ModifierFlags.Private))) {
32352
+ error(node.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter);
32353
+ }
32329
32354
32330
- // TypeScript 1.0 spec (April 2014): 4.5
32331
- // If both accessors include type annotations, the specified types must be identical.
32332
- checkAccessorDeclarationTypesAssignable(node, otherAccessor, getAnnotatedAccessorType, Diagnostics.get_and_set_accessor_must_have_the_comparable_types);
32355
+ checkAccessorDeclarationTypesAssignable(getter, setter, getAnnotatedAccessorType, Diagnostics.The_return_type_of_a_get_accessor_must_be_assignable_to_its_set_accessor_type);
32333
32356
checkAccessorDeclarationTypesIdentical(node, otherAccessor, getThisTypeOfDeclaration, Diagnostics.get_and_set_accessor_must_have_the_same_this_type);
32334
32357
}
32335
32358
}
@@ -32345,8 +32368,8 @@ namespace ts {
32345
32368
return checkAccessorDeclarationTypesMatch(first, second, getAnnotatedType, isTypeIdenticalTo, message);
32346
32369
}
32347
32370
32348
- function checkAccessorDeclarationTypesAssignable(first : AccessorDeclaration, second : AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type | undefined, message: DiagnosticMessage) {
32349
- return checkAccessorDeclarationTypesMatch(first, second , getAnnotatedType, areTypesComparable , message);
32371
+ function checkAccessorDeclarationTypesAssignable(getter : AccessorDeclaration, setter : AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type | undefined, message: DiagnosticMessage) {
32372
+ return checkAccessorDeclarationTypesMatch(getter, setter , getAnnotatedType, isTypeAssignableTo , message);
32350
32373
}
32351
32374
32352
32375
function checkAccessorDeclarationTypesMatch(first: AccessorDeclaration, second: AccessorDeclaration, getAnnotatedType: (a: AccessorDeclaration) => Type | undefined, match: typeof areTypesComparable, message: DiagnosticMessage) {
@@ -32357,7 +32380,6 @@ namespace ts {
32357
32380
}
32358
32381
}
32359
32382
32360
-
32361
32383
function checkMissingDeclaration(node: Node) {
32362
32384
checkDecorators(node);
32363
32385
}
@@ -40171,7 +40193,7 @@ namespace ts {
40171
40193
}
40172
40194
40173
40195
function checkGrammarAccessor(accessor: AccessorDeclaration): boolean {
40174
- if (!(accessor.flags & NodeFlags.Ambient)) {
40196
+ if (!(accessor.flags & NodeFlags.Ambient) && (accessor.parent.kind !== SyntaxKind.TypeLiteral) && (accessor.parent.kind !== SyntaxKind.InterfaceDeclaration) ) {
40175
40197
if (languageVersion < ScriptTarget.ES5) {
40176
40198
return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher);
40177
40199
}
0 commit comments