mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:32:08 -06:00
Improve error message for index signature on generic type when writing (#55906)
This commit is contained in:
parent
413179867f
commit
b1f5ef69e8
@ -17845,7 +17845,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (indexInfo) {
|
||||
if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo.keyType !== numberType) {
|
||||
if (accessExpression) {
|
||||
error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType));
|
||||
if (accessFlags & AccessFlags.Writing) {
|
||||
error(accessExpression, Diagnostics.Type_0_is_generic_and_can_only_be_indexed_for_reading, typeToString(originalObjectType));
|
||||
}
|
||||
else {
|
||||
error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType));
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -3699,6 +3699,10 @@
|
||||
"category": "Error",
|
||||
"code": 2861
|
||||
},
|
||||
"Type '{0}' is generic and can only be indexed for reading.": {
|
||||
"category": "Error",
|
||||
"code": 2862
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
cannotIndexGenericWritingError.ts(4,5): error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
cannotIndexGenericWritingError.ts(8,5): error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
|
||||
|
||||
==== cannotIndexGenericWritingError.ts (2 errors) ====
|
||||
// From #47357
|
||||
|
||||
function foo<T extends Record<string | symbol, any>>(target: T, p: string | symbol) {
|
||||
target[p] = ""; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
}
|
||||
|
||||
function foo2<T extends number[] & { [s: string]: number | string }>(target: T, p: string | number) {
|
||||
target[p] = 1; // error
|
||||
~~~~~~~~~
|
||||
!!! error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
target[1] = 1; // ok
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
//// [tests/cases/compiler/cannotIndexGenericWritingError.ts] ////
|
||||
|
||||
=== cannotIndexGenericWritingError.ts ===
|
||||
// From #47357
|
||||
|
||||
function foo<T extends Record<string | symbol, any>>(target: T, p: string | symbol) {
|
||||
>foo : Symbol(foo, Decl(cannotIndexGenericWritingError.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(cannotIndexGenericWritingError.ts, 2, 13))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>target : Symbol(target, Decl(cannotIndexGenericWritingError.ts, 2, 53))
|
||||
>T : Symbol(T, Decl(cannotIndexGenericWritingError.ts, 2, 13))
|
||||
>p : Symbol(p, Decl(cannotIndexGenericWritingError.ts, 2, 63))
|
||||
|
||||
target[p] = ""; // error
|
||||
>target : Symbol(target, Decl(cannotIndexGenericWritingError.ts, 2, 53))
|
||||
>p : Symbol(p, Decl(cannotIndexGenericWritingError.ts, 2, 63))
|
||||
}
|
||||
|
||||
function foo2<T extends number[] & { [s: string]: number | string }>(target: T, p: string | number) {
|
||||
>foo2 : Symbol(foo2, Decl(cannotIndexGenericWritingError.ts, 4, 1))
|
||||
>T : Symbol(T, Decl(cannotIndexGenericWritingError.ts, 6, 14))
|
||||
>s : Symbol(s, Decl(cannotIndexGenericWritingError.ts, 6, 38))
|
||||
>target : Symbol(target, Decl(cannotIndexGenericWritingError.ts, 6, 69))
|
||||
>T : Symbol(T, Decl(cannotIndexGenericWritingError.ts, 6, 14))
|
||||
>p : Symbol(p, Decl(cannotIndexGenericWritingError.ts, 6, 79))
|
||||
|
||||
target[p] = 1; // error
|
||||
>target : Symbol(target, Decl(cannotIndexGenericWritingError.ts, 6, 69))
|
||||
>p : Symbol(p, Decl(cannotIndexGenericWritingError.ts, 6, 79))
|
||||
|
||||
target[1] = 1; // ok
|
||||
>target : Symbol(target, Decl(cannotIndexGenericWritingError.ts, 6, 69))
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
//// [tests/cases/compiler/cannotIndexGenericWritingError.ts] ////
|
||||
|
||||
=== cannotIndexGenericWritingError.ts ===
|
||||
// From #47357
|
||||
|
||||
function foo<T extends Record<string | symbol, any>>(target: T, p: string | symbol) {
|
||||
>foo : <T extends Record<string | symbol, any>>(target: T, p: string | symbol) => void
|
||||
>target : T
|
||||
>p : string | symbol
|
||||
|
||||
target[p] = ""; // error
|
||||
>target[p] = "" : ""
|
||||
>target[p] : any
|
||||
>target : T
|
||||
>p : string | symbol
|
||||
>"" : ""
|
||||
}
|
||||
|
||||
function foo2<T extends number[] & { [s: string]: number | string }>(target: T, p: string | number) {
|
||||
>foo2 : <T extends number[] & { [s: string]: string | number; }>(target: T, p: string | number) => void
|
||||
>s : string
|
||||
>target : T
|
||||
>p : string | number
|
||||
|
||||
target[p] = 1; // error
|
||||
>target[p] = 1 : 1
|
||||
>target[p] : any
|
||||
>target : T
|
||||
>p : string | number
|
||||
>1 : 1
|
||||
|
||||
target[1] = 1; // ok
|
||||
>target[1] = 1 : 1
|
||||
>target[1] : number
|
||||
>target : T
|
||||
>1 : 1
|
||||
>1 : 1
|
||||
}
|
||||
@ -24,7 +24,7 @@ keyofAndIndexedAccess2.ts(52,3): error TS2322: Type 'number' is not assignable t
|
||||
keyofAndIndexedAccess2.ts(53,3): error TS2322: Type 'number' is not assignable to type 'T[K]'.
|
||||
'T[K]' could be instantiated with an arbitrary type which could be unrelated to 'number'.
|
||||
keyofAndIndexedAccess2.ts(65,7): error TS2339: Property 'foo' does not exist on type 'T'.
|
||||
keyofAndIndexedAccess2.ts(66,3): error TS2536: Type 'string' cannot be used to index type 'T'.
|
||||
keyofAndIndexedAccess2.ts(66,3): error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
keyofAndIndexedAccess2.ts(67,3): error TS2322: Type 'number' is not assignable to type 'T[keyof T]'.
|
||||
'number' is assignable to the constraint of type 'T[keyof T]', but 'T[keyof T]' could be instantiated with a different subtype of constraint 'number'.
|
||||
keyofAndIndexedAccess2.ts(68,3): error TS2322: Type 'number' is not assignable to type 'T[K]'.
|
||||
@ -146,7 +146,7 @@ keyofAndIndexedAccess2.ts(108,5): error TS2322: Type '123' is not assignable to
|
||||
!!! error TS2339: Property 'foo' does not exist on type 'T'.
|
||||
obj[k1] = 123; // Error
|
||||
~~~~~~~
|
||||
!!! error TS2536: Type 'string' cannot be used to index type 'T'.
|
||||
!!! error TS2862: Type 'T' is generic and can only be indexed for reading.
|
||||
obj[k2] = 123; // Error
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'T[keyof T]'.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
mappedTypeGenericWithKnownKeys.ts(9,9): error TS2551: Property 'unknownLiteralKey' does not exist on type 'Record<keyof Shape | "knownLiteralKey", number>'. Did you mean 'knownLiteralKey'?
|
||||
mappedTypeGenericWithKnownKeys.ts(10,5): error TS2536: Type 'string' cannot be used to index type 'Record<keyof Shape | "knownLiteralKey", number>'.
|
||||
mappedTypeGenericWithKnownKeys.ts(10,5): error TS2862: Type 'Record<keyof Shape | "knownLiteralKey", number>' is generic and can only be indexed for reading.
|
||||
|
||||
|
||||
==== mappedTypeGenericWithKnownKeys.ts (2 errors) ====
|
||||
@ -16,6 +16,6 @@ mappedTypeGenericWithKnownKeys.ts(10,5): error TS2536: Type 'string' cannot be u
|
||||
!!! error TS2551: Property 'unknownLiteralKey' does not exist on type 'Record<keyof Shape | "knownLiteralKey", number>'. Did you mean 'knownLiteralKey'?
|
||||
obj['' as string] = 4; // error
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2536: Type 'string' cannot be used to index type 'Record<keyof Shape | "knownLiteralKey", number>'.
|
||||
!!! error TS2862: Type 'Record<keyof Shape | "knownLiteralKey", number>' is generic and can only be indexed for reading.
|
||||
}
|
||||
|
||||
13
tests/cases/compiler/cannotIndexGenericWritingError.ts
Normal file
13
tests/cases/compiler/cannotIndexGenericWritingError.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
// From #47357
|
||||
|
||||
function foo<T extends Record<string | symbol, any>>(target: T, p: string | symbol) {
|
||||
target[p] = ""; // error
|
||||
}
|
||||
|
||||
function foo2<T extends number[] & { [s: string]: number | string }>(target: T, p: string | number) {
|
||||
target[p] = 1; // error
|
||||
target[1] = 1; // ok
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user