piotrwitek / utility-types

Collection of utility types, complementing TypeScript built-in mapped types and aliases (think "lodash" for static types).
MIT License
5.54k stars 230 forks source link

`FilterKeys`, `OmitByCondition`, `PickByCondition` (more flexible variants of `Pick` and `Omit`) #194

Open Antonzo opened 7 months ago

Antonzo commented 7 months ago

Is your feature request related to a real problem or use-case?

Sometimes the requirement involves manipulating an object's keys based not strictly on their key types but on other characteristics of the keys, such as key patterns. For these cases Pick or Omit are insufficient.

Describe a solution including usage in code example

Solution:

type FilterKeys<T, Condition> = {
  [K in keyof T]: K extends Condition ? K : never
}[keyof T];

type PickByCondition<T, Condition> = Pick<T, FilterKeys<T, Condition>>;
type OmitByCondition<T, Condition> = Omit<T, FilterKeys<T, Condition>>;

Example:

type AppConfig = {
  dev_databaseUrl: string;
  dev_databaseUser: string;
  prod_databaseUrl: string;
  prod_databaseUser: string;
  common_logLevel: string;
};

type DevelopmentConfig = PickByCondition <AppConfig, `dev_${string}`>;

type NonDevelopmentKeys = OmitByCondition<AppConfig, `dev_${string}`>;

Who does this impact? Who is this for?

For cases where it is important to distinguish between parts of keys, such as prefixes or suffixes. Can be used when key entities differ in some property and therefore there are several variations of keys. As in the example above, key entities are divided into dev and prod (runtime environments).