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 infer names declared in a sibling array property?

I’m defining two different groups: Tabs and Sections. A section exists inside tabs.(Tabs contain sections).

When declaring sections, I’d like to have the tab names to be automatically filled by the sibling tabs that were just declared.

But how to infer the names of siblings? Here’s what I tried (Try it on playground):

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

export type TabDeclaration<TabName extends string = string> = {
  name?: TabName;
};

export type SectionDeclaration<
  Tabs extends TabDeclaration[],
  SectionName extends string = string
> = Tabs extends TabDeclaration<infer TabName>[]
  ? {
      name?: SectionName;
      tab?: TabName;
    }
  : never;

type TabsAndSections<Tabs extends TabDeclaration[] = TabDeclaration[]> = {
  tabs: Tabs;
  sections: SectionDeclaration<Tabs>[];
};

var tabsAndSections: TabsAndSections = {
  tabs: [
    {
      name: 'Tab 1'
    },
    {
      name: 'Tab 2'
    }
  ],
  sections: [
    {
      name: 'Section 1',
      tab: '' /* <---- Should autocomplete "Tab 1" or "Tab 2" */
    }
  ]
}

tab: should autocomplete "Tab 1" or "Tab 2".

>Solution :

You can create an identity helper function that infers the valid tab names from the passed in values.

The second type parameter L is constrained to K so the tab names in the sections can only be taken from the tabs

Playground

type Section<K extends string> = {
  name?: string;
  tab?: K;
}

type Tab<K extends string> = {
  name: K;
};

type TabsAndSections<K extends string, L extends K> = {
  tabs: Array<Tab<K>>,
  sections: Array<Section<L>>;
};

const asTabsAndSections = <K extends string, L extends K>(
  obj: TabsAndSections<K, L>
): TabsAndSections<K, L> => obj;

const tabsAndSections = asTabsAndSections({
  tabs: [
    {
      name: 'Tab 1'
    },
    {
      name: 'Tab 2'
    }
  ],
  sections: [
    {
      name: 'Section 1',
      tab: 'Tab 1' /* <---- Should autocomplete "Tab 1" or "Tab 2" */
    }
  ]
})
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