Unfortunately the compiler won't be able to verify this for you, and in cases like this where you know more the compiler, a reasonable solution is to use a type assertion:
class Class<T> {
f<K extends keyof T>(k: K, v: T[K]) {
const badPartial: Partial<T> = { [k]: v }; // error!
const goodPartial: Partial<T> = { [k]: v } as Pick<T, K> & Partial<T>; // okay
}
}
So that's what you need to do. But why is it like this? There seem to be two main stumbling blocks that the compiler is facing.
The first stumbling block is that the compiler only knows how to interpret computed properties if the key is a single statically known literal or unique symbol type:
const k1 = "a";
const o1 = { [k1]: 123 };
// const o1: {[k1]: number};
o1.a; // okay
o1.b; // error
If, instead, if the key type is generic or a union of string literals, the compiler widens it to string and treats the resulting object as one with a string index signature, to strange results:
const k2 = Math.random() < 0.5 ? "a" : "z";
const o2 = { [k2]: 123 };
// const o2: {[x: string]:number};
o2.a; // no error, but might not exist
o2.b; // no error, but *definitely* doesn't exist
function foo<K extends string>(k3: K) {
const o3 = { [k3]: 123 };
// const o3: {[x: string]:number};
o3.a; // no error, but probably doesn't exist
}
This is an open issue in TypeScript; see microsoft/TypeScript#13948. It's sort of clear what the "right thing" to do would be for the case of unions of literals; presumably o2 above should be of type {a: number} | {z: number}. It's less clear with generics; perhaps o3 above should be of type Partial<Record<K, number>>. In any case, a string index signature isn't great and breaks things like you've seen.
Another stumbling block is that even if the compiler realized that the computed property was assignable to some suitable type depending on generic types T and K, it probably wouldn't be able to recognize that this type is assignable to Partial<T>. It's easy enough for a human being to see this, but the compiler can't necessarily reason about higher order type manipulation of this sort. The canonical open issue about this is probably microsoft/TypeScript#28884, where the issue is that Pick<T, K> & Omit<T, K> is not seen as compatible with T, when T or K is generic. For any statically known type T and K, the compiler could do the analysis: Pick<{a: string, b: string}, "a"> & Omit<{a: string, b: string}, "a"> is indeed seen as assignable to {a: string, b: string}. But once you make the types generic, the compiler essentially gives up.
For both of those reasons, there's little chance of getting the compiler to verify the assignability for you. And the best advice I can give is to use that type assertion and move on.
Okay, hope that helps; good luck!
Playground link to code
string; and even if you narrow it toP, the compiler still can't verify in the generic case. You'll need to use a type assertion like{ [key]: defaultValue } as Pick<T, P> as Partial<T>. If those other answers don't cover your issue let me know