How to infer a type that depends on the previous type which isn't used in function parameters

26 Views Asked by At

interface User {
    id?: number;
    name?: string;
    email?: string;
    gender?: string;
    status?: string;
}

export const foo = <T extends object, P extends keyof T>(payload: User, pick_keys: P[]) => {
    const result = pick(payload, ['email', 'gender']) as T;

    return pick(result, pick_keys);
};

const {} = foo<User>({ name: 'hh', id: 33 }, ['name', 'id']);

why the type P isn't being infered from the passed in array of keys ? and i get a red underline under foo<User>(...);

saying that Expected 2 type arguments, but got 1

1

There are 1 best solutions below

2
ij7 On BEST ANSWER

The problem is that you either have to provide all type arguments, or have all of them inferred. You cannot provide only some: https://github.com/microsoft/TypeScript/issues/26242

The only, slightly ugly, solution that I'm aware of is an outer function with one type parameter (which you'll explicitly provide) which returns an inner function with one type parameter (that'll be inferred).

Something like this:

function foo_outer<T extends object>() {
  return <P extends keyof T>(payload: User, pick_keys: P[]) => {
    // ...
  };
}

Then you can do this:

foo_outer<User>()({ name: 'hh', id: 33 }, ['name', 'id'])
            // ^-- note the extra pair of parens