You will see some incoherences in typescript syntax

We can write the following to extract a subset of properties of an object into a separate object. The following code works properly and is fully typed.

const subset: <T, K extends keyof T>(o: T, props: K[]) => Readonly<{ [P in K]: T[P]; }> = (o, props) => {
    const retO = {} as {[P in typeof props[number]]: typeof o[P]};
    props.forEach(
        p => retO[p] = o[p]
    );
    return Object.freeze(retO);
};
const fullA = { a: 1, b: "", c: 3, };
const subsetOfA = subset(fullA, ["a", "b"]);
console.log(subsetOfA);

Now if we decide to abstract some bit of code that seems to be repeated like this bit:

{ [P in K]: T[P]; }

which is meaning the same as this one in the function body:

{ [P in typeof props[number]]: typeof o[P]; }

using the Pick<T, K extends keyof T> type, we get this:

const subset: <T, K extends keyof T>(o: T, props: K[]) => Readonly<{[P in K]: T[P]}> = (o, props) => {
   const retO = {} as Pick<typeof o, typeof props[number]>; //changed this line only
   props.forEach(
       p => retO[p] = o[p]
   );
   return Object.freeze(retO);
};

And if you test it, it will behave in exactly the same way as the initial function. However, if we take it one step further and replace the return type using the Pick syntax:

const subset: <T, K extends keyof T>(o: T, props: K[]) => Readonly<Pick<T, K>> = (o, props) => { // changed this line too
    const retO = {} as Pick<typeof o, typeof props[number]>;
    props.forEach(
        p => retO[p] = o[p]
    );
    return Object.freeze(retO);
};

it stops working. Instead the return type is not a subset anymore.

Why

The problem seems to be that we are passing the full set of properties defined in the type variable K. And what we really want to pass is only the subset of the keys passed in props: K[]. How do we tell TypeScript to reference those keys only? I do not see any other way than using the [P in K] construct as in the initial definition.