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

Handle objects with properties that can be of multiple types in Angular

I’m trying to build a search screen that uses tabs to switch between different input methods but I’m running into a Typescript error because my base object allows multiple types whereas my custom input component doesn’t.

In the parent component I have an array of objects of type Tab to define all the tabs

export interface Tab {
  id: string,
  name: string,
  desc: string,
  type: string,
  isCurrent: boolean,
  value: string | number | Checkbox[] | IDate
}

I iterate over this array, and produce different HTML based on the tab type

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

However, because value can be multiple different data types I get errors when I try to produce checkboxes, because I need to iterate over an array. e.g. *ngFor produces the error because tab.value might not be an array, it might be a number etc.

      <div class="govuk-form-group" *ngIf="tab.type === 'checkbox'">
        <fieldset class="govuk-fieldset" aria-describedby="{tab.id + 'hint'}">
          <div class="govuk-checkboxes" data-module="govuk-checkboxes">
            <div class="govuk-checkboxes__item" *ngFor="let checkbox of tab.value">
              <input class="govuk-checkboxes__input" id="{{checkbox.id}}" name="{{checkbox.id}}" type="checkbox" [(ngModel)]="checkbox.selected">
              <label class="govuk-label govuk-checkboxes__label" for="{{checkbox.id}}">
                {{checkbox.name}}
              </label>
            </div>
          </div>
        </fieldset>
      </div>

I have tried to use a child component, whereby Tab.value is redefined in the child as being of type Checkbox[] only and passing the tab object from parent to child. But then I get an error saying that one is not assignable to the other, which makes perfect sense because value can hold different types in both Interfaces.

Is there any way I can satisfy the Type checking, without resorting to using any?

>Solution :

Here is a way you could handle that while keeping your html exactly as is and just changing your types.
It’s a bit verbose but it lets TypeScript infer the type of the value property from the value of the type property

export type Tab = StringTab | NumberTab | DateTab | CheckboxTab;

interface TabBase {
    id: string,
    name: string,
    desc: string,
    isCurrent: boolean
}

interface StringTab extends TabBase {
    type: "string",
    value: string
}

interface NumberTab extends TabBase {
    type: "number",
    value: number
}

interface DateTab extends TabBase {
    type: "date",
    value: IDate
}

interface CheckboxTab extends TabBase {
    type: "checkbox",
    value: Checkbox[]
}
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