1

I want to create some interface to be used as a type for objects that have two properties and the names of those properties are based on an 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
}

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

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 =)
};

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.