Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write PickByValue type?

Tags:

typescript

The Pick type is included with TypeScript. It's implementation is as follows:

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

How would you write a PickByValue type such that the following works:

type Test = {
  includeMe: 'a' as 'a',
  andMe: 'a' as 'a',
  butNotMe: 'b' as 'b',
  orMe: 'b' as 'b'
};

type IncludedKeys = keyof PickByValue<Test, 'a'>;
// IncludedKeys = 'includeMe' | 'andMe'
like image 602
Braden Snell Avatar asked Mar 13 '19 20:03

Braden Snell


1 Answers

Assuming you intend Test to be this:

type Test = {
  includeMe: 'a',
  andMe: 'a',
  butNotMe: 'b',
  orMe: 'b'
};

and assuming that you want PickByValue<T, V> to give all the properties which are subtypes of V (so that PickByValue<T, unknown> should be T), then you can define PickByValue like this:

type PickByValue<T, V> = Pick<T, { [K in keyof T]: T[K] extends V ? K : never }[keyof T]>
type TestA = PickByValue<Test, 'a'>; // {includeMe: "a"; andMe: "a"}
type IncludedKeys = keyof PickByValue<Test, 'a'>; // "includeMe" | "andMe"

But if all you want is IncludedKeys, then you can do that more directly with KeysMatching<T, V>:

type KeysMatching<T, V> = {[K in keyof T]: T[K] extends V ? K : never}[keyof T];
type IncludedKeysDirect = KeysMatching<Test, 'a'> // "includeMe" | "andMe"

Playground link to code

like image 128
jcalz Avatar answered Oct 18 '22 12:10

jcalz