Home > Enterprise >  How to get type of picked property instead of subset of supertype in TypeScript?
How to get type of picked property instead of subset of supertype in TypeScript?

Time:03-28

Assume there is a supertype A:

type A = {
  q: {
    x1: string;
    x2: number;
  };
  p: number;
};

const aObj: A = {
  q: {
    x1: 'jj',
    x2: 3,
  },
  p: 5,
};

const fn = <T extends string & keyof A>(path: keyof A): Pick<A, T> => {
  return aObj[path];
};

const fn2 = <T extends string & keyof A>(path: keyof A): A[T] => {
  return aObj[path];
};

The code above raises the following error TS 2322:

 Type "number | { x1: string; x2: number; }" is not assignable to type "A[T]".
  Type "number" is not assignable to type "A[T]".
    Type "number" is not assignable to type "{ x1: string; x2: number; } & number".
      Type "number" is not assignable to type "{ x1: string; x2: number; }".

Now, I want to write a generic function fn that returns the type of the picked property Pick<A, "p" | "q">, that is (number) | ({ x1: string, x2: number }), depending on the specified generic argument.

However, Pick only returns a subset of all the picked properties of A.

Replacing Pick by square brackets does not seem to do the job either.

What is the right way to get the type of the picked property instead of just a subset?

CodePudding user response:

You can have something like:

const fn2 = <T extends keyof A>(path: T): A[T] => {
  return aObj[path];
};

You can check this at TypeScript playground

As per your codebase, since there is no corelation between T and typeof path (i.e. keyof A). TypeScript is not able to determine what should be the return type. i.e. for path p, whether it should be number or it should be { x1: string, x2: number }.

  • Related