Home > Back-end >  How to infer a type that depends on the previous type which isn't used in function parameters
How to infer a type that depends on the previous type which isn't used in function parameters

Time:10-23


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

CodePudding user response:

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
  • Related