Reputation: 2624
I have this function
function foo<T extends { [P in K]: number }, K extends keyof T>(obj: T, key: K): void {
const x: number = obj[key]
obj[key] = 123 //error
}
obj[key]
has type number
but I cannot write number to it
Type '123' is not assignable to type 'T[K]'.
How to fix it?
Upvotes: 3
Views: 74
Reputation: 3485
This is working as intended. Imagine you invoke foo
like this:
const obj = {a: 42} as const
foo(obj,"a")
// foo<{readonly a: 42; }, "a">(obj: { readonly a: 42; }, key: "a"): void
Then T[K]
won't be number
, but 42
(a subtype) - an assignment of 123
to a
wouldn't be valid anymore. Inside foo
body, we only know for sure, that T[K]
is some kind of number
(generic constraint of T
), but not what the exact type is.
Hence TS will emit the error Type '123' is not assignable to type 'T[K]'
- the compiler cannot ensure, that 123
is the right type, as generic types are set by the caller of foo
. The only type that can be checked statically is T[K]
.
To write number
to certain properties K
, you can change the signature as follows:
function foo<K extends PropertyKey>(obj: Record<K, number>, key: K): void {
const x: number = obj[key]
obj[key] = 123
}
const obj = { foo: 1, bar: true }
foo(obj, 'foo') // works
Upvotes: 4