Search code examples
typescriptkeyof

Can't use keyof to assign to a field


I would like some explanation about this error I encounter:

interface Test {
    a: number;
    b: string;
    c: string;
}
function f(obj1: Test, obj2: Test, field: keyof Test) {
    obj1[field] = obj2[field]; // Error: Type 'string | number' is not assignable to type 'never'.
}

Here are some ways I found to circumvent that error:

  • if Test contains only numbers or only strings
  • if I use obj1[field as string] = obj2[field]
  • if I change my method to function f<K extends keyof Test>(obj1: Test, obj2: Test, field: K)

But I don't understand why this code fails, is it a "bug" in typescript or am I missing something ?


Solution

  • That's because TypeScript doesn't know what type will be returned by obj2[field]. It can be either number or string. In addition, TypeScript doesn't know what type of obj1[field] will be. And because it is number | string so it decides, for type safety, that it will be never, because there are no types that is base for both number and string. Additionally, TypeScript doesn't know which property name will be in field

    if Test contains only numbers or only strings

    In that case, TypeScript definitely knows that all fields will be number or string, so it can infer types for both obj1[field] and obj2[field], and it will be the same type.

    if I change my method to function f(obj1: Test, obj2: Test, field: K)

    In that case TypeScript knows exactly type for both obj1[field] and obj2[field], so it can safely assign value.