6

"Using Type Parameters in Generic Constraints" in the TypeScript site shows the example code below. But the following error occurred:

'Type 'U[keyof U]' is not assignable to type 'T[keyof U]'. Type 'U' is not assignable to type 'T'.'

function copyFields<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = source[id];
    }
    return target;
}
let x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 });

In fact, this does not run in the Playground. What is wrong with the code?

2
  • It's surprising that the code in the docs doesn't compile. I'd recommend filing an issue in the github.com/Microsoft/TypeScript-Handbook repo about this Commented Jan 5, 2017 at 5:52
  • 1
    I posted the issue and got a reply. Commented Jan 6, 2017 at 1:41

1 Answer 1

4

It makes sense that U is not assignable to T since the object satisfying U could have additional fields that T doesn't have:

interface Foo { foo: number; }
interface Bar extends Foo { bar: number; }
interface Bar2 extends Foo { bar: string; }

function assign<T extends U, U>(b: U): T {
    const returnVal: T = b;  // error: Type 'U' is not assignable to type 'T'.
    return returnVal;
}

const bar2: Bar2 = { foo: 7, bar: "happy" };
assign<Bar, Foo>(bar2);

So, since U isn't assignable to T, there's no way we can guarantee that a specific U[keyof U] is assignable to T[keyof U].

(I'm not 100% confident in this explanation, but it seems to make sense to me.)


However, by modifying how you type things, you can write a version of copyFields that works as intended, like this:

function copyFields<T, K extends keyof T>(target: T, source: Pick<T, K>) {
    for (let id in source) {
        target[id] = source[id];
    }
    return target;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your answer. I understood your explanation. And revised code works fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.