Merge pull request #17710 from Microsoft/add-readonly-check-to-property-access-of-index-signature
Add readonly check to property access of index signature
This commit is contained in:
commit
146f828919
|
@ -7576,7 +7576,6 @@ namespace ts {
|
|||
if (indexInfo) {
|
||||
if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
|
||||
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
|
||||
return unknownType;
|
||||
}
|
||||
return indexInfo.type;
|
||||
}
|
||||
|
@ -7617,7 +7616,6 @@ namespace ts {
|
|||
}
|
||||
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && type.declaration.readonlyToken) {
|
||||
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(type));
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(type)], [indexType]);
|
||||
|
@ -14615,9 +14613,12 @@ namespace ts {
|
|||
}
|
||||
const prop = getPropertyOfType(apparentType, right.escapedText);
|
||||
if (!prop) {
|
||||
const stringIndexType = getIndexTypeOfType(apparentType, IndexKind.String);
|
||||
if (stringIndexType) {
|
||||
return stringIndexType;
|
||||
const indexInfo = getIndexInfoOfType(apparentType, IndexKind.String);
|
||||
if (indexInfo && indexInfo.type) {
|
||||
if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) {
|
||||
error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType));
|
||||
}
|
||||
return indexInfo.type;
|
||||
}
|
||||
if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) {
|
||||
reportNonexistentProperty(right, type.flags & TypeFlags.TypeParameter && (type as TypeParameter).isThisType ? apparentType : type);
|
||||
|
@ -17138,7 +17139,9 @@ namespace ts {
|
|||
if (operandType === silentNeverType) {
|
||||
return silentNeverType;
|
||||
}
|
||||
const ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand),
|
||||
const ok = checkArithmeticOperandType(
|
||||
node.operand,
|
||||
checkNonNullType(operandType, node.operand),
|
||||
Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
|
||||
if (ok) {
|
||||
// run check only if former checks succeeded to avoid reporting cascading errors
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(6,31): error TS2540: Cannot assign to 'A' because it is a constant or a read-only property.
|
||||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(7,29): error TS2540: Cannot assign to 'A' because it is a constant or a read-only property.
|
||||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(10,9): error TS2540: Cannot assign to 'A' because it is a constant or a read-only property.
|
||||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(12,1): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type.
|
||||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(12,1): error TS2542: Index signature in type 'typeof ENUM1' only permits reading.
|
||||
tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts(12,7): error TS2304: Cannot find name 'A'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts (5 errors) ====
|
||||
==== tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOperatorWithEnumType.ts (6 errors) ====
|
||||
// -- operator on enum type
|
||||
|
||||
enum ENUM1 { A, B, "" };
|
||||
|
@ -25,6 +26,9 @@ tests/cases/conformance/expressions/unaryOperators/decrementOperator/decrementOp
|
|||
|
||||
ENUM1[A]--;
|
||||
~~~~~~~~
|
||||
!!! error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type.
|
||||
~~~~~~~~
|
||||
!!! error TS2542: Index signature in type 'typeof ENUM1' only permits reading.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'A'.
|
||||
!!! error TS2304: Cannot find name 'A'.
|
||||
|
|
@ -10,7 +10,8 @@ var ResultIsNumber2 = ENUM1.A--;
|
|||
// miss assignment operator
|
||||
--ENUM1["A"];
|
||||
|
||||
ENUM1[A]--;
|
||||
ENUM1[A]--;
|
||||
|
||||
|
||||
//// [decrementOperatorWithEnumType.js]
|
||||
// -- operator on enum type
|
||||
|
|
|
@ -58,7 +58,19 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2
|
|||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(51,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(56,5): error TS2542: Index signature in type 'Readonly<T>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
|
||||
Type 'T[string]' is not assignable to type 'U[keyof T]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
|
||||
Type 'T[string]' is not assignable to type 'U[K]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
Type 'T' is not assignable to type 'U'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(66,5): error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(72,5): error TS2322: Type 'Partial<T>' is not assignable to type 'T'.
|
||||
tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(78,5): error TS2322: Type 'Partial<Thing>' is not assignable to type 'Partial<T>'.
|
||||
|
@ -88,7 +100,7 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
Type 'T' is not assignable to type 'U'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/mapped/mappedTypeRelationships.ts (28 errors) ====
|
||||
==== tests/cases/conformance/types/mapped/mappedTypeRelationships.ts (30 errors) ====
|
||||
function f1<T>(x: T, k: keyof T) {
|
||||
return x[k];
|
||||
}
|
||||
|
@ -227,6 +239,13 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
x[k] = y[k];
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
~~~~
|
||||
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
}
|
||||
|
||||
|
@ -234,6 +253,13 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS
|
|||
x[k] = y[k];
|
||||
y[k] = x[k]; // Error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[K]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[K]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T[string]' is not assignable to type 'U[string]'.
|
||||
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||
~~~~
|
||||
!!! error TS2542: Index signature in type 'Readonly<U>' only permits reading.
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
tests/cases/compiler/objectFreeze.ts(9,1): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/compiler/objectFreeze.ts(9,1): error TS2542: Index signature in type 'ReadonlyArray<number>' only permits reading.
|
||||
tests/cases/compiler/objectFreeze.ts(12,3): error TS2540: Cannot assign to 'b' because it is a constant or a read-only property.
|
||||
|
||||
|
||||
==== tests/cases/compiler/objectFreeze.ts (2 errors) ====
|
||||
==== tests/cases/compiler/objectFreeze.ts (3 errors) ====
|
||||
const f = Object.freeze(function foo(a: number, b: string) { return false; });
|
||||
f(1, "") === false;
|
||||
|
||||
|
@ -13,6 +14,8 @@ tests/cases/compiler/objectFreeze.ts(12,3): error TS2540: Cannot assign to 'b' b
|
|||
const a = Object.freeze([1, 2, 3]);
|
||||
a[0] = a[2].toString();
|
||||
~~~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
~~~~
|
||||
!!! error TS2542: Index signature in type 'ReadonlyArray<number>' only permits reading.
|
||||
|
||||
const o = Object.freeze({ a: 1, b: "string" });
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
tests/cases/compiler/propertyAccessOfReadonlyIndexSignature.ts(6,1): error TS2542: Index signature in type 'Test' only permits reading.
|
||||
|
||||
|
||||
==== tests/cases/compiler/propertyAccessOfReadonlyIndexSignature.ts (1 errors) ====
|
||||
interface Test {
|
||||
readonly [key: string]: string;
|
||||
}
|
||||
|
||||
declare var a: Test;
|
||||
a.foo = 'baz';
|
||||
~~~~~
|
||||
!!! error TS2542: Index signature in type 'Test' only permits reading.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
//// [propertyAccessOfReadonlyIndexSignature.ts]
|
||||
interface Test {
|
||||
readonly [key: string]: string;
|
||||
}
|
||||
|
||||
declare var a: Test;
|
||||
a.foo = 'baz';
|
||||
|
||||
|
||||
//// [propertyAccessOfReadonlyIndexSignature.js]
|
||||
a.foo = 'baz';
|
|
@ -0,0 +1,6 @@
|
|||
interface Test {
|
||||
readonly [key: string]: string;
|
||||
}
|
||||
|
||||
declare var a: Test;
|
||||
a.foo = 'baz';
|
|
@ -9,4 +9,4 @@ var ResultIsNumber2 = ENUM1.A--;
|
|||
// miss assignment operator
|
||||
--ENUM1["A"];
|
||||
|
||||
ENUM1[A]--;
|
||||
ENUM1[A]--;
|
||||
|
|
Loading…
Reference in a new issue