Everything is functioning as anticipated. Picture yourself calling the foo
function like this:
const obj = {a: 42} as const
foo(obj,"a")
// foo<{readonly a: 42; }, "a">(obj: { readonly a: 42; }, key: "a"): void
In this scenario, T[K]
would not be of type number
, but rather 42
(which is a subtype) - attempting to assign 123
to a
would no longer be valid. Within the body of the foo
function, we can only be certain that T[K]
represents some sort of number
due to the generic constraint on T
, but we cannot determine the exact type.
Therefore, TypeScript will generate the error message
Type '123' is not assignable to type 'T[K]'
- the compiler cannot guarantee that
123
is the correct type since generic types are dictated by the
caller of the
foo
function. The only statically checkable type is
T[K]
.
To allow writing number
to specific properties K
, you can modify the function signature as shown below:
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') // it will work
Sample on TS Playground