Silo QIAN
Silo QIAN

Reputation: 60

How to Omit property in type by property type

i have a type with some properties typed string, number, etc..., and i want to omit some properties who's type isn't string.

the Omit<T, U> generic just omit by property name, but not property type.

for example:

class Person {
  name: string;
  age: number;
  eat(food: Food): void;
  walk(miles: number): void;
  read(book: Book): void;
}

// =>

type PersonAbility = PickAbility<Person>;

// how can i write a PickAbility<T> generic, results:

type PersonAbility = {
  eat(food: Food): void;
  walk(miles: number): void;
  read(book: Book): void;
}

as the code above.

and i have try this:

type PersonAbility = {
  [K in keyof Person]: Person[K] extends (payload: {}) => Promise<{}> ? Person[K] : never
};

// it results:

type PersonAbility = {
  name: never;
  age: never;
  eat: (food: Food) => void;
  walk: (miles: number) => void;
  read: (book: Book) => void;
}

the codes above set the property not needed to never, but not remove it.

Upvotes: 2

Views: 1112

Answers (1)

jcalz
jcalz

Reputation: 329903

The solution here is to get the union of keys corresponding to the property values you want, and then Pick those. Here's one way to do it:

type KeysMatching<T, V> = {
  [K in keyof T]-?: T[K] extends V ? K : never
}[keyof T];

KeysMatching<T, V> uses a mapped, conditional, and lookup type to find the keys of type T whose property values are assignable to type V.

Then we can make PickMatching<T, V> which just Picks those values:

type PickMatching<T, V> = Pick<T, KeysMatching<T, V>>;

And PickAbility<T> will just use PickMatching on Function-valued properties (your example code uses (payload: {}) => Promise<{}> but none of your Person methods match that):

type PickAbility<T> = PickMatching<T, Function>;

Let's test it:

type PersonAbility = PickAbility<Person>;
/*
type PersonAbility = {
    eat: (food: Food) => void;
    walk: (miles: number) => void;
    read: (book: Book) => void;
}
*/

Looks good. Hope that help; good luck!

Link to code

Upvotes: 5

Related Questions