Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to type several property keys based on Enum?

I have dilemma. I want to create some interface to type object when should be two properties with specific key names based on enum… You can see my solution below but I think it’s not flexible.

enum DiapasonBorders {
  MinInclude = 'minInclude',
  MinExclude = 'minExclude',
  MaxInclude = 'maxInclude',
  MaxExclude = 'maxExclude'
}

interface CaseA {
  [DiapasonBorders.MinInclude]: number;
  [DiapasonBorders.MaxInclude]: number;
}

interface CaseB {
  [DiapasonBorders.MinInclude]: number;
  [DiapasonBorders.MaxExclude]: number;
}

interface CaseC {
  [DiapasonBorders.MinExclude]: number;
  [DiapasonBorders.MaxInclude]: number;
}

interface CaseD {
  [DiapasonBorders.MinExclude]: number;
  [DiapasonBorders.MaxExclude]: number;
}

export type DiapasonBordersSetting = CaseA | CaseB | CaseC | CaseD;

so now I can create object when can be only one property with "min" and only one with "max"
e.g

const obj: DiapasonBordersSetting = {
  minInclude: 4,
  maxExclude: 56
}

const obj2: DiapasonBordersSetting = {
  minExclude: 4,
  maxExclude: 56
}

Maybe anybody have some ideas how to improve this code? Something like:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

type MinExcludeOrInclude = DiapasonBorders.MinInclude | DiapasonBorders.MinExclude;
type MaxExcludeOrInclude = DiapasonBorders.MaxInclude | DiapasonBorders.MaxExclude;

type DiapasonBordersSetting = {
  [minKey in MinExcludeOrInclude]: number;
  [maxKey in MaxExcludeOrInclude]: number; // yes mistake over here =)
};

>Solution :

One solution could look like this:

type MinExcludeOrInclude = DiapasonBorders.MinInclude | DiapasonBorders.MinExclude;
type MaxExcludeOrInclude = DiapasonBorders.MaxInclude | DiapasonBorders.MaxExclude;

export type DiapasonBordersSetting = {
  [K in MinExcludeOrInclude]: {
    [K2 in MaxExcludeOrInclude]: Record<K | K2, number>
  }[MaxExcludeOrInclude]
}[MinExcludeOrInclude] extends infer O ? { [K in keyof O]: O[K] } : never

By mapping over MinExcludeOrInclude and MaxExcludeOrInclude we can construct a Record for each combination.

Playground


You might also be interested in a way of defining MinExcludeOrInclude without manually listing every member.

type MinExcludeOrInclude = GetByPrefix<"min">
type MaxExcludeOrInclude = GetByPrefix<"max">

export type GetByPrefix<P extends string> = {
  [K in DiapasonBorders as K extends `${P}${string}` ? K : never]: K
} extends infer O ? O[keyof O] : never
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading