mod7ex
mod7ex

Reputation: 948

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


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

Upvotes: 0

Views: 30

Answers (1)

ij7
ij7

Reputation: 369

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

Upvotes: 1

Related Questions